c语言编程,关于不规则三角网的边界提取的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言编程,关于不规则三角网的边界提取的相关的知识,希望对你有一定的参考价值。

我现在知道不规则三角网(TIN)的所有三维顶点坐标,现在要提取这个三角网的边界点,我有这个想法,每个边界点之间的边长只被一个三角形共有,内部三角形的边被两个三角形共有。根据这个可以提取出边界。请问怎么用c语言实现啊?我这儿有数据,如果可以请留下邮箱,我发给你。
我的点都是三维坐标点,还有z值,建立队列我不太熟悉,能否根据我的思路来做?

我的一点想法,提取边界,(所有点的x,y坐标已知)
步骤
1.建立一个已有边界点队列,初始为空
2.首先找第一点(x,y),提取y坐标最小值的点,若存在相同y坐标,任意取一点即可
3.将该点(x,y)加入边界点队列
4.从(x,y)点开始,标记该点位发起点,依次遍历除了边界点队列中已存在点以外的所有点(x1,y1)。
5.计算x y 与 x1, y1之间的仰角关系,找出所有中仰角最小的点(x1,y1),可通过两点之间的斜率进行计算,注意存在正负关系,(存在相同仰角关系,因此还需要记录两点之间的长度,当仰角相同时取长度短的点)
6.将该点(x1,y1)加入边界队列(从此步骤开始,重复步骤3,4, 5)迭代,直到一直检索到最初始点后,边界计算完成

献丑了,看错题目当成二维坐标。

三维坐标可能麻烦些,我的一些想法,个人未验证过,仅供提示,希望有所帮助
步骤
1.提取z坐标最小的点,若存在多个点,任意取一点。
2.建立一个连接线记录队列,初始为空
3.遍历所有该点以外的所有点,找出仰角最小的点,以这两点的连接线记录。
4.遍历除了连接线记录队列中已有连接线端点外的所有点(x,y,z),计算该连接线与点(x,y,z)组成的平面,与除了这平面三点以外的所有其他点与该平面的垂距关系(存在正负关系),若所有其他点都在该平面的同侧,即正负关系一致,则确定该三点平面为边界三角形的一个,将三角形的三边加入连接线记录队列
5.(从本步骤开始,以该边界三角网的除初始边外的另两边进行步骤4的迭代,当迭代到找不到除已有连接线记录队列中点以外的符合条件的点为止)
这样就完成的所有边界点的计算了。

对于你的算法,我感觉有所纰漏,边界三角形的边也有可能被多个三角形所共用的。

个人愚见,未经验证,请勿拍砖
参考技术A 是的,如果一条边只被一个三角形拥有,它就是边界。

你的三角网含不含“岛屿”,含个数不定的“岛屿”程序要复杂一些。

我常用的有限元网文件:
x1 y1 z1 // node 座标
x2 y2 z2
....
xi yi zi
...
xn yn zn
n11 n12 n13 // 构成三角形1 3顶点号
n21 n22 n23 // 构成三角形2 3顶点号
n31 n32 n33 // 。。。
n41 n42 n43
...本回答被提问者采纳

为啥我们选择“边界框”的方式来填充三角形呢?

【中文标题】为啥我们选择“边界框”的方式来填充三角形呢?【英文标题】:Why do we choose the "bounding box" method to fill a triangle?为什么我们选择“边界框”的方式来填充三角形呢? 【发布时间】:2017-02-28 05:57:07 【问题描述】:

我正在 GitHub 上学习一门短期课程“How OpenGL works: software rendering in 500 lines of code”。在lesson 2,作者正在教我们如何用颜色填充三角形。他想出了两种方法:

    枚举三角形内的所有水平线段,并绘制这些线段。作者的代码如下。

    void triangle(Vec2i t0, Vec2i t1, Vec2i t2, TGAImage &image, TGAColor color)  
        if (t0.y==t1.y && t0.y==t2.y) return; // I dont care about degenerate triangles 
        // sort the vertices, t0, t1, t2 lower−to−upper (bubblesort yay!) 
        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 i=0; i<total_height; i++)  
            bool second_half = i>t1.y-t0.y || t1.y==t0.y; 
            int segment_height = second_half ? t2.y-t1.y : t1.y-t0.y; 
            float alpha = (float)i/total_height; 
            float beta  = (float)(i-(second_half ? t1.y-t0.y : 0))/segment_height; // be careful: with above conditions no division by zero here 
            Vec2i A =               t0 + (t2-t0)*alpha; 
            Vec2i B = second_half ? t1 + (t2-t1)*beta : t0 + (t1-t0)*beta; 
            if (A.x>B.x) std::swap(A, B); 
            for (int j=A.x; j<=B.x; j++)  
                image.set(j, t0.y+i, color); // attention, due to int casts t0.y+i != A.y 
             
         
    
    

    找到三角形的边界框。枚举边界框中的所有点,并使用重心坐标检查该点是否在三角形内。如果该点在三角形中,则用颜色填充该点。作者的代码如下。

    Vec3f barycentric(Vec2i *pts, Vec2i P)  
        Vec3f u = cross(Vec3f(pts[2][0]-pts[0][0], pts[1][0]-pts[0][0], pts[0][0]-P[0]), Vec3f(pts[2][1]-pts[0][1], pts[1][1]-pts[0][1], pts[0][1]-P[1])); 
        if (std::abs(u[2])<1) return Vec3f(-1,1,1); // triangle is degenerate, in this case return smth with negative coordinates 
        return Vec3f(1.f-(u.x+u.y)/u.z, u.y/u.z, u.x/u.z); 
     
    
    void triangle(Vec2i *pts, TGAImage &image, TGAColor color)  
        Vec2i bboxmin(image.get_width()-1,  image.get_height()-1); 
        Vec2i bboxmax(0, 0); 
        Vec2i clamp(image.get_width()-1, image.get_height()-1); 
        for (int i=0; i<3; i++)  
            for (int j=0; j<2; j++)  
                bboxmin[j] = std::max(0,        std::min(bboxmin[j], pts[i][j])); 
                bboxmax[j] = std::min(clamp[j], std::max(bboxmax[j], pts[i][j])); 
             
         
        Vec2i P; 
        for (P.x=bboxmin.x; P.x<=bboxmax.x; P.x++)  
            for (P.y=bboxmin.y; P.y<=bboxmax.y; P.y++)  
                Vec3f bc_screen  = barycentric(pts, P); 
                if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0) continue; 
                image.set(P.x, P.y, color); 
             
         
     
    

作者在第2课结束时选择了第二种方法,但我不明白为什么。是因为效率的原因,还是因为第二种方法更容易理解?

【问题讨论】:

第二种方法可以比第一种方法更好地并行化,因为调用的数量不会因行而异。 【参考方案1】:

重心坐标用于在三角形的每个顶点处插入或“涂抹”值。例如:如果我定义一个三角形 ABC,我可以给每个顶点一个颜色,分别是红色、绿色和蓝色。然后当我填写三角形时,我可以使用重心坐标(α、β、γ)得到一个线性组合 P = α * Red + beta * Blue + gamma * Green 来确定三角形内某个点的颜色应该是。

此过程经过高度优化并内置于 GPU 硬件中。您可以涂抹任何您想要的值,包括法线向量(通常用于逐像素光照计算),因此这是一个非常有用的操作。

当然,我不知道你的老师在想什么,但我敢猜测,在未来的课程中,他们可能会讨论这个问题,所以第二个算法自然会引发讨论。

来源:https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates

【讨论】:

以上是关于c语言编程,关于不规则三角网的边界提取的的主要内容,如果未能解决你的问题,请参考以下文章

如何用C语言编程序:输入三个数,判断是不是构成三角形

关于JAVA语言,和C语言有啥联系吗?

求解一道Python编程题(求代码)

关于c语言判断电话号码合法问题

C语言编程 关于计算时间的问题 望高手解答!

C语言 编写函数,输入三角形三边之长,求三角形面积。