w15 <<
Previous Next >> ANS 1
try Do
第一次嘗試(錯誤答案)
// https://en.wikipedia.org/wiki/Flag_of_the_Republic_of_China
// 內政部國旗參考資料: https://www.moi.gov.tw/cp.aspx?n=10621
// cc roc_flag_in_gd.c -lgd -lm to link with gd and math library
// https://www.rapidtables.com/web/color/RGB_Color.html
// 幾何形狀著色與繪圖練習
// 以下 gd 繪圖程式嘗試畫出 ROC 國旗, 請根據下列程式內容完成後續的國旗繪圖
#include <stdio.h>
#include <gd.h>
#include <math.h>
void draw_roc_flag(gdImagePtr img);
void draw_white_sun(gdImagePtr img, int x, int y, int size, int color);
int main() {
// width 3: height 2
int width = 1200;
// 國旗長寬比為 3:2
int height = (int)(width*2.0 / 3.0);
gdImagePtr img = gdImageCreateTrueColor(width, height);
gdImageAlphaBlending(img, 0);
draw_roc_flag(img);
FILE *outputFile = fopen("roc_flag_in_gd.png", "wb");
if (outputFile == NULL) {
fprintf(stderr, "Error opening the output file.\n");
return 1;
}
gdImagePngEx(img, outputFile, 9);
fclose(outputFile);
gdImageDestroy(img);
return 0;
}
void draw_roc_flag(gdImagePtr img) {
int width = gdImageSX(img);
int height = gdImageSY(img);
int red, white, blue;
// 白日位於青天面積正中央, 因此中心點座標為長寬各 1/4 處
int center_x = (int)(width/4);
int center_y = (int)(height/4);
// gdImageFilledEllipse 需以長寬方向的 diameter 作圖
// 由於中央白日圓形的半徑為青天寬度的 1/8
// 因此中央白日圓形的直徑為青天寬度的 1/4, 也就是國旗寬度的 1/8
// 而且白日十二道光芒的外圍圓形其半徑也是國旗寬度的1/8
int sun_radius = (int)(width/8);
// 中央白日圓形的直徑等於十二道光芒外圍圓形的半徑
int white_circle_dia = sun_radius;
// 中央藍色圓形半徑為中央白日的 1又 2/15
int blue_circle_dia = white_circle_dia + white_circle_dia*2/15;
// 根據 https://www.moi.gov.tw/cp.aspx?n=10621 訂定國旗三種顏色值
red = gdImageColorAllocate(img, 255, 0, 0); // 紅色
white = gdImageColorAllocate(img, 255, 255, 255); // 白色
blue = gdImageColorAllocate(img, 0, 0, 149); // 藍色
// 根據畫布大小塗上紅色長方形區域
gdImageFilledRectangle(img, 0, 0, width, height, red);
// 青天面積為整面國旗的 1/4, 也是採用長方形塗色
gdImageFilledRectangle(img, 0, 0, (int)(width/2.0), (int)(height/2.0), blue);
// 先設法以填色畫出六個白色堆疊菱形
draw_white_sun(img, center_x, center_y, sun_radius, white);
// 利用一個藍色大圓與白色小圓畫出藍色環狀
gdImageFilledEllipse(img, center_x, center_y, blue_circle_dia, blue_circle_dia, blue);
gdImageFilledEllipse(img, center_x, center_y, white_circle_dia, white_circle_dia, white);
}
void draw_white_sun(gdImagePtr img, int center_x, int center_y, int sun_radius, int color) {
// M_PI 大小定義於 math.h 標頭檔中, 因為三角函數中採用徑度為角度單位
// 因此定義將角度轉為徑度的轉換變數為 deg, 角度值乘上 deg 就可轉為徑度
float deg = M_PI/180;
// 根據十二道光芒的每一尖角的角度為 15 度, 求出其對應直角三角形的另一角度為 75 度
// 求出十二道光芒中任一菱形的 small radius, 也就是菱形的另一個對應小圓的半徑大小
float sr = sun_radius/tan(75*deg);
int ax, ay, bx, by, dx, dy, ex, ey;
gdPoint points[4];
/* 在塗上十二道光芒中的單一菱形區域之前, 先以座標點畫線測試是否正確
ax = center_x;
ay = center_y - sun_radius;
bx = center_x - sun_radius*tan(15*deg);
by = center_y;
ex = center_x;
ey = center_y + sun_radius;
dx = center_x + sun_radius*tan(15*deg);
dy = center_y;
// AB
gdImageLine(img, ax, ay, bx, by, color);
// BE
gdImageLine(img, bx, by, ex, ey, color);
// ED
gdImageLine(img, ex, ey, dx, dy, color);
// DA
gdImageLine(img, dx, dy, ax, ay, color);
*/
ax = center_x;
ay = center_y - sun_radius;
printf("%d,%d\n",ax, ay);
bx = center_x - sun_radius*tan(15*deg);
by = center_y;
ex = center_x;
ey = center_y + sun_radius;
dx = center_x + sun_radius*tan(15*deg);
dy = center_y;
// 確定單一菱形區域的塗色正確後, 利用迴圈每次轉動 30 度, 總共轉六次即可塗上十二道光芒區域
for (int i=1;i<=6;i++){
// A
points[0].x = ax+sun_radius*sin(30*deg*i);
points[0].y = ay+sun_radius-sun_radius*cos(30*deg*i);
printf("A coord: (%d,%d)\n", points[0].x, points[0].y);
// B
points[1].x = bx+sr-sr*cos(30*deg*i);
points[1].y = by-sr*sin(30*deg*i);
printf("B coord: (%d,%d)\n", points[1].x, points[1].y);
// E
points[2].x = ex-sun_radius*sin(30*deg*i);
points[2].y = ey-(sun_radius-sun_radius*cos(30*deg*i));
printf("E coord: (%d,%d)\n", points[2].x, points[2].y);
// D
points[3].x = dx-(sr-sr*cos(30*deg*i));
points[3].y = dy+sr*sin(30*deg*i);
printf("D coord: (%d,%d)\n\n", points[2].x, points[2].y);
// 對菱形區域範圍塗色
gdImageFilledPolygon(img, points, 4, color);
// 在菱形區域外圍畫線, 明確界定菱形範圍
gdImagePolygon(img, points, 4, color);
}
}
第二次製作(有點是答案)
#include <stdio.h>
#include <gd.h>
#include <math.h>
void draw_roc_flag(gdImagePtr img);
void draw_white_sun(gdImagePtr img, int x, int y, int size, int color);
void connectPoints(gdImagePtr img, int x1, int y1, int x2, int y2, int color);
int main() {
// width 3: height 2
int width = 1200;
// 國旗長寬比為 3:2
int height = (int)(width * 2.0 / 3.0);
gdImagePtr img = gdImageCreateTrueColor(width, height);
gdImageAlphaBlending(img, 0);
draw_roc_flag(img);
FILE *outputFile = fopen("Y:/tmp/c_ex/roc_flag_in_gd.png", "wb");
if (outputFile == NULL) {
fprintf(stderr, "Error opening the output file.\n");
return 1;
}
gdImagePngEx(img, outputFile, 9);
fclose(outputFile);
gdImageDestroy(img);
return 0;
}
void draw_roc_flag(gdImagePtr img) {
int width = gdImageSX(img);
int height = gdImageSY(img);
int red, white, blue;
// 白日位於青天面積正中央, 因此中心點座標為長寬各 1/4 處
int center_x = (int)(width / 4);
int center_y = (int)(height / 4);
// gdImageFilledEllipse 需以長寬方向的 diameter 作圖
// 由於中央白日圓形的半徑為青天寬度的 1/8
// 因此中央白日圓形的直徑為青天寬度的 1/4, 也就是國旗寬度的 1/8
// 而且白日十二道光芒的外圍圓形其半徑也是國旗寬度的1/8
int sun_radius = (int)(width / 8);
// 中央白日圓形的直徑等於十二道光芒外圍圓形的半徑
int white_circle_dia = sun_radius;
// 中央藍色圓形半徑為中央白日的 1又 2/15
int blue_circle_dia = white_circle_dia + white_circle_dia * 2 / 15;
// 根據 https://www.moi.gov.tw/cp.aspx?n=10621 訂定國旗三種顏色值
red = gdImageColorAllocate(img, 255, 0, 0); // 紅色
white = gdImageColorAllocate(img, 255, 255, 255); // 白色
blue = gdImageColorAllocate(img, 0, 0, 149); // 藍色
// 根據畫布大小塗上紅色長方形區域
gdImageFilledRectangle(img, 0, 0, width, height, red);
// 青天面積為整面國旗的 1/4, 也是採用長方形塗色
gdImageFilledRectangle(img, 0, 0, (int)(width / 2.0), (int)(height / 2.0), blue);
// 先設法以填色畫出六個白色堆疊菱形
draw_white_sun(img, center_x, center_y, sun_radius, white);
// 利用一個藍色大圓與白色小圓畫出藍色環狀
gdImageFilledEllipse(img, center_x, center_y, blue_circle_dia, blue_circle_dia, blue);
gdImageFilledEllipse(img, center_x, center_y, white_circle_dia, white_circle_dia, white);
// 連接四個座標點
connectPoints(img, 429, 125, 279, 165, white);
connectPoints(img, 279, 165, 170, 274, white);
connectPoints(img, 170, 274, 319, 234, white);
connectPoints(img, 319, 234, 429, 125, white);
}
void draw_white_sun(gdImagePtr img, int center_x, int center_y, int sun_radius, int color) {
float deg = M_PI / 180;
float sr = sun_radius / tan(75 * deg);
int ax, ay, bx, by, dx, dy, ex, ey;
ax = center_x;
ay = center_y - sun_radius;
bx = center_x - sun_radius * tan(15 * deg);
by = center_y;
ex = center_x;
ey = center_y + sun_radius;
dx = center_x + sun_radius * tan(15 * deg);
dy = center_y;
for (int i = 1; i <= 6; i++) {
int ax1 = ax + sun_radius * sin(30 * deg * i);
int ay1 = ay + sun_radius - sun_radius * cos(30 * deg * i);
int bx1 = bx + sr - sr * cos(30 * deg * i);
int by1 = by - sr * sin(30 * deg * i);
int ex1 = ex - sun_radius * sin(30 * deg * i);
int ey1 = ey - (sun_radius - sun_radius * cos(30 * deg * i));
int dx1 = dx - (sr - sr * cos(30 * deg * i));
int dy1 = dy + sr * sin(30 * deg * i);
// 對菱形區域範圍塗色
gdImageFilledPolygon(img, (gdPoint[4]){{ax1, ay1}, {bx1, by1}, {ex1, ey1}, {dx1, dy1}}, 4, color);
// 在菱形區域外圍畫線,明確界定菱形範圍
gdImageLine(img, ax1, ay1, bx1, by1, color);
gdImageLine(img, bx1, by1, ex1, ey1, color);
gdImageLine(img, ex1, ey1, dx1, dy1, color);
gdImageLine(img, dx1, dy1, ax1, ay1, color);
}
}
void connectPoints(gdImagePtr img, int x1, int y1, int x2, int y2, int color) {
gdImageLine(img, x1, y1, x2, y2, color);
配合ChatGTP,在原式上新增
gdImageLine(img, ax1, ay1, bx1, by1, color);
gdImageLine(img, bx1, by1, ex1, ey1, color);
gdImageLine(img, ex1, ey1, dx1, dy1, color);
gdImageLine(img, dx1, dy1, ax1, ay1, color);
}
}
這個還不是正確答案還需將白色太陽塗色部分跟非第二組座標連成的線條移除
第三次製作(以為是答案)
#include <stdio.h>
#include <gd.h>
#include <math.h>
void draw_roc_flag(gdImagePtr img);
void draw_white_sun(gdImagePtr img, int x, int y, int size, int color);
//void connectPoints(gdImagePtr img, int x1, int y1, int x2, int y2, int color);
int main() {
// width 3: height 2
int width = 1200;
// 國旗長寬比為 3:2
int height = (int)(width * 2.0 / 3.0);
gdImagePtr img = gdImageCreateTrueColor(width, height);
gdImageAlphaBlending(img, 0);
draw_roc_flag(img);
FILE *outputFile = fopen("Y:/tmp/c_ex/roc_flag_04_gd.png", "wb");
if (outputFile == NULL) {
fprintf(stderr, "Error opening the output file.\n");
return 1;
}
gdImagePngEx(img, outputFile, 9);
fclose(outputFile);
gdImageDestroy(img);
return 0;
}
void draw_roc_flag(gdImagePtr img) {
int width = gdImageSX(img);
int height = gdImageSY(img);
int red, white, blue;
// 白日位於青天面積正中央, 因此中心點座標為長寬各 1/4 處
int center_x = (int)(width / 4);
int center_y = (int)(height / 4);
// gdImageFilledEllipse 需以長寬方向的 diameter 作圖
// 由於中央白日圓形的半徑為青天寬度的 1/8
// 因此中央白日圓形的直徑為青天寬度的 1/4, 也就是國旗寬度的 1/8
// 而且白日十二道光芒的外圍圓形其半徑也是國旗寬度的1/8
int sun_radius = (int)(width / 8);
// 中央白日圓形的直徑等於十二道光芒外圍圓形的半徑
int white_circle_dia = sun_radius;
// 中央藍色圓形半徑為中央白日的 1又 2/15
int blue_circle_dia = white_circle_dia + white_circle_dia * 2 / 15;
// 根據 https://www.moi.gov.tw/cp.aspx?n=10621 訂定國旗三種顏色值
red = gdImageColorAllocate(img, 255, 0, 0); // 紅色
white = gdImageColorAllocate(img, 255, 255, 255); // 白色
blue = gdImageColorAllocate(img, 0, 0, 149); // 藍色
// 根據畫布大小塗上紅色長方形區域
gdImageFilledRectangle(img, 0, 0, width, height, red);
// 青天面積為整面國旗的 1/4, 也是採用長方形塗色
gdImageFilledRectangle(img, 0, 0, (int)(width / 2.0), (int)(height / 2.0), blue);
// 先設法以填色畫出六個白色堆疊菱形
//draw_white_sun(img, center_x, center_y, sun_radius, white);
// 利用一個藍色大圓與白色小圓畫出藍色環狀
//gdImageFilledEllipse(img, center_x, center_y, blue_circle_dia, blue_circle_dia, blue);
//gdImageFilledEllipse(img, center_x, center_y, white_circle_dia, white_circle_dia, white);
{int x1 = 429;
int y1 = 125;
int x2 = 279;
int y2 = 165;
// 畫一條線連接兩個點
gdImageLine(img, x1, y1, x2, y2, white);
}
{int x1 = 170;
int y1 = 274;
int x2 = 279;
int y2 = 165;
// 畫一條線連接兩個點
gdImageLine(img, x1, y1, x2, y2, white);
}
{
int x1 = 170;
int y1 = 274;
int x2 = 429;
int y2 = 125;
// 畫一條線連接兩個點
gdImageLine(img, x1, y1, x2, y2, white);
}
}
//void connectPoints(gdImagePtr img, int x1, int y1, int x2, int y2, int color) {
//gdImageLine(img, x1, y1, x2, y2, color);
誤以為這就是解答,一開時候第四個點看錯,導致變成三角形。
第二題(錯誤答案)
#include <stdio.h>
#include <gd.h>
#include <math.h>
// 定義座標結構
typedef struct {
double x;
double y;
} Point;
// Function prototypes
void draw_roc_flag(gdImagePtr img);
void draw_white_sun(gdImagePtr img, int x, int y, int size, int color);
void connectPoints(gdImagePtr img, int x1, int y1, int x2, int y2, int color);
Point circleLineIntersection(double h, double k, double r, double x1, double y1, double x2, double y2);
int main() {
// width 3: height 2
int width = 1200;
// 國旗長寬比為 3:2
int height = (int)(width*2.0 / 3.0);
gdImagePtr img = gdImageCreateTrueColor(width, height);
gdImageAlphaBlending(img, 0);
draw_roc_flag(img);
FILE *outputFile = fopen("Y:/tmp/c_ex/roc_flag_07_gd_2.png", "wb");
if (outputFile == NULL) {
fprintf(stderr, "Error opening the output file.\n");
return 1;
}
gdImagePngEx(img, outputFile, 9);
fclose(outputFile);
gdImageDestroy(img);
return 0;
}
void connectPoints(gdImagePtr img, int x1, int y1, int x2, int y2, int color) {
gdImageLine(img, x1, y1, x2, y2, color);
}
// ... connectPoints 函式的實作 ...
// 實作 draw_white_sun 函式
// 修改 circleLineIntersection 函式
Point circleLineIntersection(double h, double k, double r, double x1, double y1, double x2, double y2) {
Point intersection;
// 直線斜率
double m = (y2 - y1) / (x2 - x1);
// 直線方程式中的常數項
double b = y1 - m * x1;
// 圓與直線交點的計算
double A = 1 + pow(m, 2);
double B = 2 * (m * b - m * k - h);
double C = pow(k, 2) - pow(r, 2) + pow(h, 2) - 2 * b * k + pow(b, 2);
// 判斷交點個數
double discriminant = pow(B, 2) - 4 * A * C;
if (discriminant > 0) {
intersection.x = (-B + sqrt(discriminant)) / (2 * A);
intersection.y = m * intersection.x + b;
printf("交點: (%.2f, %.2f)\n", intersection.x, intersection.y);
intersection.x = (-B - sqrt(discriminant)) / (2 * A);
intersection.y = m * intersection.x + b;
printf("交點: (%.2f, %.2f)\n", intersection.x, intersection.y);
} else if (discriminant == 0) {
intersection.x = -B / (2 * A);
intersection.y = m * intersection.x + b;
printf("交點: (%.2f, %.2f)\n", intersection.x, intersection.y);
} else {
printf("No points.\n");
}
return intersection;
}
// 完成 draw_roc_flag 函式
void draw_roc_flag(gdImagePtr img) {
int width = gdImageSX(img);
int height = gdImageSY(img);
int red, white, blue;
// 白日位於青天面積正中央, 因此中心點座標為長寬各 1/4 處
int center_x = (int)(width / 4);
int center_y = (int)(height / 4);
// gdImageFilledEllipse 需以長寬方向的 diameter 作圖
// 由於中央白日圓形的半徑為青天寬度的 1/8
// 因此中央白日圓形的直徑為青天寬度的 1/4, 也就是國旗寬度的 1/8
// 而且白日十二道光芒的外圍圓形其半徑也是國旗寬度的1/8
int sun_radius = (int)(width / 8);
// 中央白日圓形的直徑等於十二道光芒外圍圓形的半徑
int white_circle_dia = sun_radius;
// 中央藍色圓形半徑為中央白日的 1又 2/15
int blue_circle_dia = white_circle_dia + white_circle_dia * 2 / 15;
// 根據 https://www.moi.gov.tw/cp.aspx?n=10621 訂定國旗三種顏色值
red = gdImageColorAllocate(img, 255, 0, 0); // 紅色
white = gdImageColorAllocate(img, 255, 255, 255); // 白色
blue = gdImageColorAllocate(img, 0, 0, 149); // 藍色
// 根據畫布大小塗上紅色長方形區域
gdImageFilledRectangle(img, 0, 0, width, height, red);
// 青天面積為整面國旗的 1/4, 也是採用長方形塗色
gdImageFilledRectangle(img, 0, 0, (int)(width / 2.0), (int)(height / 2.0), blue);
// 先設法以填色畫出六個白色堆疊菱形
connectPoints(img, 429, 125, 279, 165, white);
connectPoints(img, 170, 274, 279, 165, white);
connectPoints(img, 170, 274, 429, 125, white);
// 利用一個藍色大圓與白色小圓畫出藍色環狀
gdImageFilledEllipse(img, center_x, center_y, blue_circle_dia, blue_circle_dia, blue);
gdImageFilledEllipse(img, center_x, center_y, white_circle_dia, white_circle_dia, white);
// 計算圓與線的交點
double circle_x = (int)(width / 4); // 圓心 x 座標
double circle_y = (int)(height / 4); // 圓心 y 座標
double radius = white_circle_dia + white_circle_dia * 2 / 15; // 圓半徑
// 兩點座標
double x3 = 170;
double y3 = 274;
double x4 = 279;
double y4 = 165;
Point intersection1 = circleLineIntersection(circle_x, circle_y, radius, x4, y4, x3, y3);
double x5 = 279;
double y5 = 165;
double x6 = 429;
double y6 = 125;
Point intersection2 = circleLineIntersection(circle_x, circle_y, radius, x6, y6, x5, y5);
// 使用交點座標,例如印出或繪製到圖片中
//printf("Intersection 1: (%.2f, %.2f)\n", intersection1.x, intersection1.y);
//printf("Intersection 2: (%.2f, %.2f)\n", intersection2.x, intersection2.y);
// ... 計算其他兩條直線的座標 ...
}
跟第一題錯的一樣,忘記第四個點,導致求出的點有誤。
w15 <<
Previous Next >> ANS 1