Chinaunix首页 | 论坛 | 博客
  • 博客访问: 60989
  • 博文数量: 13
  • 博客积分: 530
  • 博客等级: 中士
  • 技术积分: 125
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-18 16:14
文章分类

全部博文(13)

文章存档

2010年(6)

2009年(7)

我的朋友

分类:

2010-01-10 12:09:26

最近做了个图形学的大作业。一开始还不知道怎么把一个三维存储的图形呈现到平面内,一天内,确实只有一天内就完成了基本的投影和消隐算法,颇有成就感!
其实在投影上作了很大的简化,仅仅把图像投影到xy平面,可想有多简单了吧~取xy坐标值即可。
消隐的实现还是破费周折的,主要步骤是:计算平面上凸包,凸包上的点标记为边界点;与边界点相连的点,通过向量的计算确定是可见内点还是不可见内点;最后递归的把可见内点的相邻点标为可见点,不可见内点的相邻点标为不可见点;任意线段根据两端的端点类型(可见内点、不可见内点、边界点)标识线段是否可见。
消隐的代码如下:

private void HideLines(Graphics g)
        {
            int i;
            for (i = 0; i < Points.Count; ++i)
                ((_3DPoint)Points[i]).type = 0;

            ArrayList EdgePoints = new ArrayList();
            GetEdges(EdgePoints);
            //for (i = 0; i < EdgePoints.Count-1; ++i)

            // g.DrawString(i + " ", new Font("Arial", 20), Brushes.Blue, new PointF(((_3DPoint)EdgePoints[i]).X, ((_3DPoint)EdgePoints[i]).Y));


            for (i = 1; i < EdgePoints.Count - 1; ++i)
            {
                _3DPoint vector1 = (_3DPoint)EdgePoints[i - 1] - (_3DPoint)EdgePoints[i],
                    vector2 = (_3DPoint)EdgePoints[i + 1] - (_3DPoint)EdgePoints[i];
                for (int j = 0; j < Points.Count; ++j)
                {
                    _3DPoint p = (_3DPoint)Points[j];
                    if (p.type != 0)
                        continue;
                    int index = Lines.IndexOf(new _3DLine(p, (_3DPoint)EdgePoints[i]));
                    if (index == -1)
                        continue;
                    _3DPoint vector3 = p - (_3DPoint)EdgePoints[i];
                    double test = vector1.CrossProduct(vector2).DotProduct(vector3);
                    if (test.CompareTo(0.0) > 0)
                        p.type = 2;
                    else if (test.CompareTo(0.0) < 0)
                        p.type = -1;
                }
            }
            Queue q = new Queue();
            for (i = 0; i < Points.Count; ++i)
            {
                _3DPoint p = (_3DPoint)Points[i];
                if (p.type == 2 || p.type == -1)
                    q.Enqueue(p);
            }
            while (q.Count > 0)
            {
                _3DPoint p = (_3DPoint)q.Dequeue();
                for (int j = 0; j < Points.Count; ++j)
                {
                    _3DPoint p1 = (_3DPoint)Points[j];
                    if (p1.type != 0)
                        continue;
                    if (Lines.IndexOf(new _3DLine(p, p1)) >= 0)
                    {
                        p1.type = p.type;
                        q.Enqueue(p1);
                    }
                }
            }

            //for (i = 0; i < Points.Count; ++i)

            //{

            // _3DPoint p = (_3DPoint)Points[i];

            // g.DrawString(p.type + " ", new Font("Arial", 20), Brushes.Blue, new PointF(p.X, p.Y));

            //}


            for (i = 0; i < Lines.Count; ++i)
            {
                _3DLine l = (_3DLine)Lines[i];
                int t1 = l.Vertex1.type, t2 = l.Vertex2.type;
                if (t1 == 2 || t2 == 2)
                {
                    l.Visible = true;
                    continue;
                }
                else if (t1 == -1 || t2 == -1)
                {
                    l.Visible = false;
                    continue;
                }
                else
                    l.Visible = true;
            }
        }

        private void GetEdges(ArrayList ps)
        {
            int i ;

            _3DPoint topest = (_3DPoint)Points[0];
            for (i = 1; i < Points.Count; ++i)
            {
                if (((_3DPoint)Points[i]).Y > topest.Y)
                    topest = (_3DPoint)Points[i];
            }
            ps.Add(topest);
            topest.type = 1;

            _3DPoint nextEdge = topest, candidate, p;
            double minAngle, lastAngle = -2 * Math.PI-1, angle;
            while (true)
            {
                minAngle = 2 * Math.PI + 1;
                candidate = null;
                for (i = 0; i < Points.Count; ++i)
                {
                    p = (_3DPoint)Points[i];
                    if (p == nextEdge || (p.type == 1 && p != topest))
                        continue;
                    angle = Math.Atan2(p.Y - nextEdge.Y, p.X - nextEdge.X);
                    if (angle > lastAngle && angle < minAngle)
                    {
                        candidate = p;
                        minAngle = angle;
                    }
                }
                if (candidate == null) break;
                lastAngle = Math.Atan2(candidate.Y - nextEdge.Y, candidate.X - nextEdge.X);
                candidate.type = 1;
                nextEdge = candidate;
                ps.Add(candidate);
                if (nextEdge == topest) break;
            }
            ps.Add((_3DPoint)ps[1]);
        }

效果颇为满意,上传个截图:
这是工程代码:
文件:3D.rar
大小:15KB
下载:下载


阅读(518) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~