黄博文的地盘

专注WEB开发,共闯编程之路。

« 用c#进行directx 3D编程:实现texture贴图的alpha通道oracle数据迁移到sql server终极解决方案 »

c#实现任意多边形分解为三角形算法

任意多边形(无论凸凹)分解为三角形,算法有很多种,我这种比较简单,容易理解和实现。

原理:任意多边形必有一个角是凸角。

方法:先找到多边形的凸角,此点和相邻的2个点构成一个三角形,然后将此点删除 ,剩余的点又构成一个多边形。

继续执行此方法,就可以将多边形分解为三角形了。

寻找多边形凸点的方法可以采用面积法。

a,b,c三点为多边形上连续的三个点。

设S = (a.X - c.X) * (b.Y - c.Y) - (a.Y - c.Y) * (b.X - c.X);
当多边形顶点是按顺时针排列的时候,if S < 0, 则b点是凸点.
当多边形顶点是按逆时针排列的时候,if S > 0, 则b点是凸点.

下面是我写的一个类。

//--------------------------------------------------------
//  Copyright (C), 2000-2008, 黄博文.
//  File name: PolygonAnalyze.cs
//  Author: flysky      Version: 1.0        Date: 2008-8-17
//  Description: 任意多边形分解为三角形
//  Others:  将一任意多边形(无论凸凹,但内部不能有空心)分解为三角形,多边形顶点顺序必须是 顺时针排列。
//--------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Drawing;

namespace PolygonAnalyze
{

    /*---------------------------------------------------------
     * 核心算法:
     * 定理:任何一个多边形至少都有一个点是凸点。
     * 1,找出多边形的一个凸点。
     * 2,此凸点与相邻的两个点构成一个三角形。
     * 3,将此凸点剔除,剩下的点又构成一个新的多边形。
     * 4,回到步骤继续进行,直到多边形剩余的顶点数小于等于个为止。
     *
     * 寻找多边形凸点的方法是面积法:
     *设a,b,c三点是多变形上连续的三个点。
     * 1,首先判断a,b,c三点构成的两条线段是否垂直,如果垂直则排除它是凸点。
     * 2,设S = (a.X - c.X) * (b.Y - c.Y) - (a.Y - c.Y) * (b.X - c.X);
     * 当多边形顶点是按顺时针排列的时候,if S < 0, b点是凸点.
     * 当多边形顶点是按逆时针排列的时候,if S > 0, b点是凸点.
     *--------------------------------------------------------*/

    class PolygonAnalyze
    {
        public PolygonAnalyze()
        {
            polygonPoint = new ArrayList();
         }

        public PolygonAnalyze(ArrayList points)
        {
            polygonPoint = points;
        }

        public PolygonAnalyze(Point[] pointList)
        {
            polygonPoint = new ArrayList ();

            for (int i = 0; i < pointList.Length; i++)
            {
                polygonPoint.Add(pointList[i]);
            }
        }

        /// <summary>
        /// 存储多边形点集的动态数组
        /// </summary>
        private ArrayList polygonPoint;

        public ArrayList PolygonPoint
        {
            get { return polygonPoint; }
            set { polygonPoint = value; }
        }

        /// <summary>
        /// 判断b点是否是凸点(多边形点集要以顺时针排列)
        /// </summary>
        /// <param name="a">b点的前一个点 </param>
        /// <param name="b">b点</param>
        /// <param name="c">b点的后一个点 </param>
        /// <returns></returns>
        private bool IsBulge(Point a, Point b, Point c)
        {
            //判断a,b,c三点组成的线段是否垂直 ,如果垂直返回false
            if (c.X - b.X == 0 && b.Y - a.Y == 0)
            {
                return false;
            }
            else if (c.Y - b.Y == 0 && b.X - a.X == 0)
            {
                return false;
            }
            else if (c.X - b.X != 0 && b.X - a.X != 0 && ((c.Y - b.Y) / (c.X - b.X) * (b.Y - a.Y) / (b.X - a.X)) == -1)
            {
                return false;
            }

            //用面积法判断b点是否是凸点。( 注意多边形顶点的顺序应是顺时针排列,如果是逆时针排列,返回值刚好相反)
            int S = (a.X - c.X) * (b.Y - c.Y) - (a.Y - c.Y) * (b.X - c.X);
            if (S < 0)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 执行分解算法,返回三角形顶点数组
        /// </summary>
        /// <returns></returns>
        public ArrayList ExcectAnalyze()
        {
            ArrayList trianglePoints = new ArrayList();

            while (polygonPoint.Count > 3)
            {
                for (int i = 0; i < polygonPoint.Count && polygonPoint.Count > 3; i++)
                {
                  ;   if (i < polygonPoint.Count - 2)
                  ;   {
                  ;       if (IsBulge((Point)polygonPoint[i], (Point)polygonPoint[i + 1], (Point)polygonPoint[i + 2]))
                  ;       {
                  ;           trianglePoints.Add((Point)polygonPoint [i]);
                  ;           trianglePoints.Add((Point)polygonPoint [i + 1]);
                  ;           trianglePoints.Add((Point)polygonPoint [i + 2]);

                &n bsp;           polygonPoint.RemoveAt(i + 1);
                  ;       }
                  ;   }
                  ;   else if (i == polygonPoint.Count - 2)
                  ;   {
                  ;       if (IsBulge((Point)polygonPoint[i], (Point)polygonPoint[i + 1], (Point)polygonPoint[0]))
                  ;       {
                  ;           trianglePoints.Add((Point)polygonPoint [i]);
                  ;           trianglePoints.Add((Point)polygonPoint [i + 1]);
                  ;           trianglePoints.Add((Point)polygonPoint [0]);

                &n bsp;           polygonPoint.RemoveAt(i + 1);
                  ;       }
                  ;   }
                  ;   else if (i == polygonPoint.Count - 1)
                  ;   {
                  ;       if (IsBulge((Point)polygonPoint[i], (Point)polygonPoint[0], (Point)polygonPoint[1]))
                  ;       {
                  ;           trianglePoints.Add((Point)polygonPoint [i]);
                  ;           trianglePoints.Add((Point)polygonPoint [0]);
                  ;           trianglePoints.Add((Point)polygonPoint [1]);

                &n bsp;           polygonPoint.RemoveAt(0);
                  ;       }
                  ;   }
                }
            }
            //将剩余的顶点加入数组
            for (int i = 0; i < polygonPoint.Count; i++)
            {
                trianglePoints.Add((Point)polygonPoint[i]);
            }

            return trianglePoints;
        }
    }

   
  
}


 

调用很简单:

假设pointlist是多边形按顺时针排列的顶点数组,

            PolygonAnalyze polygon = new PolygonAnalyze(pointlist);

 

            ArrayList ary = polygon.ExcectAnalyze();
 

这个ary就是分解后的三角形的顶点列表。

  • quote 1.人杰
  • ####       ##
    ## ####   #### 
     ##  ## ## ## 
     ##   ## ##  
      ##    ##  
      ##   ##   
       ##  ##   
       ## ##    
        ####    
        ##     
    有例外情况.
    flysky 于 2008-12-12 15:52:39 回复
    那种情况下有问题?能否详细说下。
  • 2008-12-11 19:29:13 回复该留言

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Devo Build 80201

蜀ICP备08002594号. All Rights Reserved.
黄博文 版权所有 huangbowen521@126.com