cp2023 40923137

  • Home
    • SMap
    • reveal
    • blog
  • About
  • Brython
  • w4-w5
    • 牛頓第二運動定律
    • mass-spring-damper 系統
    • Eulers Method 數值分析
  • w6-w8
    • 程式練習-1 程式碼練習
    • 程式練習-2 繪製國旗
  • w11
  • w12
  • w13
  • w15
  • w16
  • 課程心得
  • 課程工具
    • Replit
    • ChatGPT
    • Microsoft-Teams
w13 << Previous Next >> w16

w15

練習題

1) 根據 roc_list_coord_flag.7z 程式內容所印出的六組 ABED 等繪製 ROC 國旗白日圖案中的菱形四個關鍵點, 請直接在青天與滿地紅的圖案中, 利用白色作為畫線顏色, 將第二組的 ABED 等四個點的座標, 以直線相連.
----------------------------------------------------------------------------------------------------------------
先將 roc_list_coord_flag.7z 下載下來,用SciTE打開roc_list_coord_flag.c,執行一次可得到一個台灣國旗以及六組座標。
#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("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);


void connectPoints(gdImagePtr img, int x1, int y1, int x2, int y2, int color) {
gdImageLine(img, x1, y1, x2, y2, color);
}
加入程式碼:
// 設置線條的粗度
gdImageSetThickness(img, 3);
// 連接四個座標點
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);

以下是完整程式碼:

#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("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);

// 設置線條的粗度
gdImageSetThickness(img, 3);

// 連接四個座標點
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);
}



\輸出結果:
------------------------------------------------------------------------------------------------
2) 承上題, 請列出第二組 ABED 的四條直線與白日中的大圓所相交 (intersect) 的四個點座標.
#include <stdio.h>
#include <gd.h>
#include <math.h>
 
void draw_roc_flag(gdImagePtr img);
 
// 函數原型
int lineCircleIntersection(int x1, int y1, int x2, int y2, int cx, int cy, int cr, int *x, int *y);
 
int main() {
    int width = 1200;
    int height = (int)(width * 2.0 / 3.0);
 
    gdImagePtr img = gdImageCreateTrueColor(width, height);
    gdImageAlphaBlending(img, 0);
 
    draw_roc_flag(img);
 
    FILE *outputFile = fopen("roc_flag2.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;
    int center_x = (int)(width / 4);
    int center_y = (int)(height / 4);
 
    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);
    gdImageFilledRectangle(img, 0, 0, (int)(width / 2.0), (int)(height / 2.0), blue);
 
    int A_x = 429;
    int A_y = 125;
    int B_x = 279;
    int B_y = 165;
    int E_x = 170;
    int E_y = 274;
    int D_x = 319;
    int D_y = 234;
 
    // Draw lines
    gdImageLine(img, A_x, A_y, B_x, B_y, white);
    gdImageLine(img, B_x, B_y, E_x, E_y, white);
    gdImageLine(img, E_x, E_y, D_x, D_y, white);
    gdImageLine(img, D_x, D_y, A_x, A_y, white);
 
    // Coordinates of the sun's circle
    int sun_center_x = (int)(width / 4);
    int sun_center_y = (int)(height / 4);
    int sun_radius = (int)(width / 8);
 
    // Draw sun's circle with reduced radius
    int new_sun_radius = sun_radius / 2;
    gdImageFilledEllipse(img, sun_center_x, sun_center_y, new_sun_radius * 2, new_sun_radius * 2, white);
 
    int intersection1_x, intersection1_y;
    int intersection2_x, intersection2_y;
    int intersection3_x, intersection3_y;
    int intersection4_x, intersection4_y;
 
    // Calculate intersections
    lineCircleIntersection(A_x, A_y, B_x, B_y, sun_center_x, sun_center_y, new_sun_radius, &intersection1_x, &intersection1_y);
    lineCircleIntersection(B_x, B_y, E_x, E_y, sun_center_x, sun_center_y, new_sun_radius, &intersection2_x, &intersection2_y);
    lineCircleIntersection(E_x, E_y, D_x, D_y, sun_center_x, sun_center_y, new_sun_radius, &intersection3_x, &intersection3_y);
    lineCircleIntersection(D_x, D_y, A_x, A_y, sun_center_x, sun_center_y, new_sun_radius, &intersection4_x, &intersection4_y);
 
    printf("Intersection 1: (%d, %d)\n", intersection1_x, intersection1_y);
    printf("Intersection 2: (%d, %d)\n", intersection2_x, intersection2_y);
    printf("Intersection 3: (%d, %d)\n", intersection3_x, intersection3_y);
    printf("Intersection 4: (%d, %d)\n", intersection4_x, intersection4_y);
}
 
// 計算直線與圓相交的座標
int lineCircleIntersection(int x1, int y1, int x2, int y2, int cx, int cy, int cr, int *x, int *y) {
    float dx, dy, A, B, C, det, t;
 
    dx = x2 - x1;
    dy = y2 - y1;
 
    A = dx * dx + dy * dy;
    B = 2 * (dx * (x1 - cx) + dy * (y1 - cy));
    C = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy) - cr * cr;
 
    det = B * B - 4 * A * C;
 
    if ((A <= 0.00001) || (det < 0)) {
        // No real solutions
        return 0;
    }
 
    t = (-B - sqrt(det)) / (2 * A);
    *x = x1 + t * dx;
    *y = y1 + t * dy;
 
    return 1;

輸出結果:

Intersection 1: (351, 145)
Intersection 2: (317, 126)
Intersection 3: (247, 253)
Intersection 4: (280, 272)


w13 << Previous Next >> w16

Copyright © All rights reserved | This template is made with by Colorlib