计算机图形学头歌实训平台答案——CG2-v2.0-三角形填充

第1关:扫描线填充法

任务描述

1. 本关任务

了解和掌握扫描线填充法,实现对三角形区域进行填充,具体要求如下: (1) 补全triangle函数; (2) 将main函数中的三角形顶点坐标和triangle函数参数补充完整。

2. 输入

(1) 三角形的三个顶点的坐标:
t0 = {125,50}, t1 = {300,200}, t2 ={200,350};
(2) 三角形区域为蓝色。

3. 输出

程序运行结果为一个蓝色三角形区域,如下图所示:

实验图片

整体代码如下:

#include "pngimage.h"
#include<stdio.h>
#include <iostream>
 
struct Vec2i
{
	int x, y;
};
 
void triangle(Vec2i t0, Vec2i t1, Vec2i t2, PNGImage& image, PNGColor color) {
    // Please add your code here
    /********** Begin ********/ 
    
    if (t0.y>t1.y) std::swap(t0, t1); 
    if (t0.y>t2.y) std::swap(t0, t2); 
    if (t1.y>t2.y) std::swap(t1, t2);
    int total_height = t2.y-t0.y;
        for (int y=t0.y; y<=t1.y; y++) { 
        int segment_height = t1.y-t0.y+1;    //be careful with divisions by 
        float alpha = (float)(y-t0.y)/total_height;      //edge t0t2
        float beta  = (float)(y-t0.y)/segment_height;    //edge t0t1 
        Vec2i A,B;
        A.y=B.y=y;
        A.x = t0.x + (t2.x-t0.x)*alpha; 
        B.x = t0.x + (t1.x-t0.x)*beta; 
        if (A.x>B.x) std::swap(A.x, B.x); 
        for (int x=A.x; x<=B.x; x++) { 
            image.set(x, y, color);  
        } 
    }
    for (int y = t1.y; y <= t2.y; y++)//感觉这个就是上半部分。
 
    {
        int segment_height = t2.y-t1.y+1;    
        float alpha2 = (float)(y-t0.y)/total_height;      //edge t0t2
        float beta2  = (float)(y-t1.y)/segment_height;    //edge t0t1 
        Vec2i A2,B2;
        A2.y=B2.y=y;
        A2.x = t0.x + (t2.x-t0.x)*alpha2; 
        B2.x = t1.x - (t1.x-t2.x)*beta2; 
        if (A2.x>B2.x) std::swap(A2.x, B2.x); 
        for (int x=A2.x; x<=B2.x; x++) { 
            image.set(x, y, color);  
        }   
    }
}
 
 
    /********** End **********/
 
 
 
int main(int argc, char** argv) {
	PNGColor white = PNGColor(255, 255, 255, 255);
	PNGColor black = PNGColor(0, 0, 0, 255);
	PNGColor red = PNGColor(255, 0, 0, 255);
    PNGColor blue = PNGColor(0, 255, 255, 255);
 
	int width = 400;
	int height = 400;
	PNGImage image(width, height, PNGImage::RGBA); //Error when RGB because lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size() in encode
	image.init(black);
    // Please add your code here


    /********** Begin ********/
    Vec2i t0 = {125 ,50 }, t1 = {300 , 200}, t2 = {200 ,350 };
	triangle( t0,t1 ,t2, image,PNGColor(0, 255, 255, 255)  );
    /********** End **********/


	image.flip_vertically(); // i want to have the origin at the left bottom corner of the image
	image.write_png_file("../img_step3/test.png");
	return 0;
}

 为防止一些刘亦菲和吴彦祖们看不出来,那小Mo就把更加简洁的代码放到下面啦

(有木有很贴心,还不给小Mo点个关注鼓励一下🥰)

(begin和end之间的代码):

代码段一:

    /********** Begin ********/ 
    if (t0.y>t1.y) std::swap(t0, t1); 
    if (t0.y>t2.y) std::swap(t0, t2); 
    if (t1.y>t2.y) std::swap(t1, t2);
    int total_height = t2.y-t0.y;
        for (int y=t0.y; y<=t1.y; y++) { 
        int segment_height = t1.y-t0.y+1;    //be careful with divisions by 
        float alpha = (float)(y-t0.y)/total_height;      //edge t0t2
        float beta  = (float)(y-t0.y)/segment_height;    //edge t0t1 
        Vec2i A,B;
        A.y=B.y=y;
        A.x = t0.x + (t2.x-t0.x)*alpha; 
        B.x = t0.x + (t1.x-t0.x)*beta; 
        if (A.x>B.x) std::swap(A.x, B.x); 
        for (int x=A.x; x<=B.x; x++) { 
            image.set(x, y, color);  
        } 
    }
    for (int y = t1.y; y <= t2.y; y++)//感觉这个就是上半部分。
 
    {
        int segment_height = t2.y-t1.y+1;    
        float alpha2 = (float)(y-t0.y)/total_height;      //edge t0t2
        float beta2  = (float)(y-t1.y)/segment_height;    //edge t0t1 
        Vec2i A2,B2;
        A2.y=B2.y=y;
        A2.x = t0.x + (t2.x-t0.x)*alpha2; 
        B2.x = t1.x - (t1.x-t2.x)*beta2; 
        if (A2.x>B2.x) std::swap(A2.x, B2.x); 
        for (int x=A2.x; x<=B2.x; x++) { 
            image.set(x, y, color);  
        }   
    }
}
    /********** End **********/

 代码段二:

    /********** Begin ********/
    Vec2i t0 = {125 ,50 }, t1 = {300 , 200}, t2 = {200 ,350 };
    triangle( t0,t1 ,t2, image,PNGColor(0, 255, 255, 255)  );
    /********** End **********/

第2关:重心坐标填充法

任务描述

1. 本关任务

了解和掌握重心坐标法,以便能够对三角形区域进行填充,具体要求如下: (1) 补全Triangle和Barycenter函数; (2) 将main函数中的三角形顶点坐标和Triangle函数参数补充完整。

2. 输入

(1) 三角形的三个顶点的坐标:
t0 = {50,50}, t1 = {300,200}, t2 ={200,350};
(2) 三角形颜色区域为绿色。

3. 输出

程序运行结果为一个绿色三角形区域,如下图所示:

test

整体代码如下:

#include "pngimage.h"
#include<stdio.h>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <stdlib.h>

struct Vec2i
{
	int x, y;
};
struct Vec3f
{
	float x, y, z;
};

//cross Product
Vec3f cross(const Vec3f& v1, const Vec3f& v2)
{
    Vec3f v3;
    v3.x = v1.y * v2.z - v1.z * v2.y;
    v3.y = v1.z * v2.x - v1.x * v2.z;
    v3.z = v1.x * v2.y - v1.y * v2.x;
    return v3;
}

//Determine the point p coordinates are in the triangle abc
Vec3f Barycentre(Vec2i p, Vec2i a, Vec2i b, Vec2i c)
{
    // Please add your code here
    /********** Begin ********/
   Vec3f v1,v2,v3,v4;
    v1.x = c.x - a.x;   v1.y = b.x - a.x;   v1.z = a.x - p.x;
    v2.x = c.y - a.y;   v2.y = b.y - a.y;   v2.z = a.y - p.y;
    v3.x = -1;          v3.y = 1;           v3.z = 1;
    Vec3f u = cross(v1, v2);
    v4.x = 1.f - (u.x + u.y) / u.z;  v4.y = u.y / u.z;  v4.z = u.x / u.z;
    if (abs(u.z) < 1) 
        return v3;
    return v4;

    /********** End ********/
}

// Please draw point to make a triangle in bounding box
void Triangle(Vec2i t0, Vec2i t1, Vec2i t2, PNGImage& image, PNGColor color)
{
    // Please add your code here
    /********** Begin ********/
    int minX = min(min(t0.x, t1.x), t2.x);
    int maxX = max(max(t0.x, t1.x), t2.x);
    int minY = min(min(t0.y, t1.y), t2.y);
    int maxY = max(max(t0.y, t1.y), t2.y);
    Vec2i P;
    for (int i = minX; i <= maxX; i++)
    {
        for (int j = minY; j <= maxY; j++)
        {
            P.x = i;
            P.y = j;
            Vec3f bc_screen = Barycentre(P, t0, t1, t2);
            if (bc_screen.x <0 || bc_screen.y <0 || bc_screen.z < 0) 
                continue;
            image.set(i, j, color);
        }
    }

    /********** End **********/
}

int main(int argc, char** argv) {
	PNGColor white = PNGColor(255, 255, 255, 255);
	PNGColor black = PNGColor(0, 0, 0, 255);
	PNGColor red = PNGColor(255, 0, 0, 255);
    PNGColor green = PNGColor(0, 255, 0, 255);    
	PNGColor blue = PNGColor(0, 255, 255, 255);
	int width = 400;
	int height = 400;
	PNGImage image(width, height, PNGImage::RGBA); //Error when RGB because lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size() in encode
	image.init(black);
    // Please add your code here
    /********** Begin ********/
    Vec2i t0 = { 50 ,50  }, t1 = { 300 ,200  }, t2 = {  200 ,350   };
    Triangle( t0, t1 ,t2  , image,green  );
    /********** End **********/
	image.flip_vertically(); // i want to have the origin at the left bottom corner of the image
	image.write_png_file("../img_step2/test.png");
	return 0;
}

按照小Mo惯例,还是把需要填写的代码段po出来喽~

代码段一:

    /********** Begin ********/
   Vec3f v1,v2,v3,v4;
    v1.x = c.x - a.x;   v1.y = b.x - a.x;   v1.z = a.x - p.x;
    v2.x = c.y - a.y;   v2.y = b.y - a.y;   v2.z = a.y - p.y;
    v3.x = -1;          v3.y = 1;           v3.z = 1;
    Vec3f u = cross(v1, v2);
    v4.x = 1.f - (u.x + u.y) / u.z;  v4.y = u.y / u.z;  v4.z = u.x / u.z;
    if (abs(u.z) < 1) 
        return v3;
    return v4;

    /********** End ********/

代码段二:

    /********** Begin ********/
    int minX = min(min(t0.x, t1.x), t2.x);
    int maxX = max(max(t0.x, t1.x), t2.x);
    int minY = min(min(t0.y, t1.y), t2.y);
    int maxY = max(max(t0.y, t1.y), t2.y);
    Vec2i P;
    for (int i = minX; i <= maxX; i++)
    {
        for (int j = minY; j <= maxY; j++)
        {
            P.x = i;
            P.y = j;
            Vec3f bc_screen = Barycentre(P, t0, t1, t2);
            if (bc_screen.x <0 || bc_screen.y <0 || bc_screen.z < 0) 
                continue;
            image.set(i, j, color);
        }
    }

    /********** End **********/

代码段三:

    /********** Begin ********/
    Vec2i t0 = { 50 ,50  }, t1 = { 300 ,200  }, t2 = {  200 ,350   };
    Triangle( t0, t1 ,t2  , image,green  );
    /********** End **********/

第三关:同侧判断填充法

任务描述:

1. 本关任务

了解和掌握同侧判断算法,以便能够对三角形区域进行填充,具体要求如下: (1) 并补全Triangle、SameSide和PointInTriangle函数; (2) 将main函数中的三角形顶点坐标和Triangle函数参数补充完整。

2. 输入

(1) 三角形的三个顶点的坐标:
t0 = {50,50}, t1 = {300,200}, t2 ={200,350};
(2) 三角形区域为红色。

3. 输出

程序运行结果为一个红色三角形区域,如下图所示:

test

整体代码如下:

#include "pngimage.h"
#include<stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct Vec2i
{
	int x, y;
};

//Cross product 
float CrossProduct(Vec2i a,Vec2i b)
{
    return a.x * b.y - b.x * a.y;
}
//DotProduct
float DotProduct(float cp1,float cp2)
{
    return cp1*cp2;
}
//Determine if P1 and P2 are on the same side
bool SameSide( Vec2i p1,Vec2i p2, Vec2i a, Vec2i b )
{
    // Please add your code here
    /********** Begin ********/
    Vec2i i,j,k;
    i.x=b.x-a.x;    i.y=b.y-a.y;
    j.x=p1.x-a.x;   j.y=p1.y-a.y;
    k.x=p2.x-a.x;   k.y=p2.y-a.y;
    float cp1 = CrossProduct(i, j),
          cp2 = CrossProduct(i, k);
    if (DotProduct(cp1, cp2) >= 0)
        return true;
    else 
        return false;


    /********** End **********/
}

//Determine the point coordinates are in the triangle
float PointInTriangle(Vec2i p,Vec2i a, Vec2i b, Vec2i c)
{
    // Please add your code here
    /********** Begin ********/
    if (SameSide(p,a, b,c) && SameSide(p,b, a,c) && SameSide(p,c, a,b) )
        return true;
    else 
        return false;

    /********** End **********/
}

// Please draw point in bounding box
void Triangle(Vec2i t0, Vec2i t1, Vec2i t2, PNGImage& image, PNGColor color)
{
    // Please add your code here
    /********** Begin ********/
    int minX = min(min(t0.x, t1.x), t2.x);
    int maxX = max(max(t0.x, t1.x), t2.x);
    int minY = min(min(t0.y, t1.y), t2.y);
    int maxY = max(max(t0.y, t1.y), t2.y);
    for (int i = minX; i <= maxX; i++)
    {
        for (int j = minY; j <= maxY; j++)
        {
            Vec2i p;
            p.x=i;
            p.y=j;
            if (PointInTriangle(p , t0 , t1 , t2)==true)
            {
                image.set(i, j, color);
            }
        }
    }


    /********** End **********/
}


int main(int argc, char** argv) {
	PNGColor white = PNGColor(255, 255, 255, 255);
	PNGColor black = PNGColor(0, 0, 0, 255);
	PNGColor red = PNGColor(255, 0, 0, 255);
    PNGColor green = PNGColor(0, 255, 0, 255);    
	PNGColor blue = PNGColor(0, 255, 255, 255);
	int width = 400;
	int height = 400;
	PNGImage image(width, height, PNGImage::RGBA); //Error when RGB because lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size() in encode
	image.init(black);
    // Please add your code here
    /********** Begin ********/
    Vec2i t0 = { 50 , 50 }, t1 = { 300 , 200 }, t2 = { 200 ,350  };
    Triangle( t0,t1  ,t2  , image,red );
    /********** End **********/
	image.flip_vertically(); // i want to have the origin at the left bottom corner of the image
	image.write_png_file("../img_step1/test.png");
	return 0;
}

同样,小Mo还是会把需要填写的代码段po出来哒~

代码段一:

    /********** Begin ********/
    Vec2i i,j,k;
    i.x=b.x-a.x;    i.y=b.y-a.y;
    j.x=p1.x-a.x;   j.y=p1.y-a.y;
    k.x=p2.x-a.x;   k.y=p2.y-a.y;
    float cp1 = CrossProduct(i, j),
          cp2 = CrossProduct(i, k);
    if (DotProduct(cp1, cp2) >= 0)
        return true;
    else 
        return false;


    /********** End **********/

代码段二:

    /********** Begin ********/
    if (SameSide(p,a, b,c) && SameSide(p,b, a,c) && SameSide(p,c, a,b) )
        return true;
    else 
        return false;

    /********** End **********/

代码段三:

    /********** Begin ********/
    int minX = min(min(t0.x, t1.x), t2.x);
    int maxX = max(max(t0.x, t1.x), t2.x);
    int minY = min(min(t0.y, t1.y), t2.y);
    int maxY = max(max(t0.y, t1.y), t2.y);
    for (int i = minX; i <= maxX; i++)
    {
        for (int j = minY; j <= maxY; j++)
        {
            Vec2i p;
            p.x=i;
            p.y=j;
            if (PointInTriangle(p , t0 , t1 , t2)==true)
            {
                image.set(i, j, color);
            }
        }
    }


    /********** End **********/

代码段四:

    /********** Begin ********/
    Vec2i t0 = { 50 , 50 }, t1 = { 300 , 200 }, t2 = { 200 ,350  };
    Triangle( t0,t1  ,t2  , image,red );
    /********** End **********/

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值