[CGPP]切角算法

文章目录[x]
  1. 1:算法描述
  2. 2:部分代码

算法描述


切角算法,亦称割角算法。首先取一条封闭的折线 (同一平面上首尾相连的一系列线段, 其实就是一个封闭的多边形啦),然后对它们进行割角操作,每条线段被分成三小段,舍弃第一小段和第三小段,余下的小段按顺序首尾连接。如下图所示:

 

部分代码


public partial class MainWindow : Window
{
    GraphPaper gp = null;
    bool ready = false;

    Polygon m_Ploygon = new Polygon();
    Polygon m_SubdivPolygon = new Polygon();
    Line m_DashLine = new Line();
    bool m_IsSubdivided = false;

    float m_Weight = 0.299f;
    
    public MainWindow()
    {
        InitializeComponent();
        InitializeCommands();
        InitializeInteraction();

        gp = Paper;

        InitPoly(m_Ploygon, Brushes.Black);
        InitPoly(m_SubdivPolygon, Brushes.Firebrick);
        InitLine(m_DashLine, Brushes.DarkBlue);
        gp.Children.Add(m_Ploygon);
        gp.Children.Add(m_SubdivPolygon);
        gp.Children.Add(m_DashLine);
        
        ready = true;
    }
    
    // 核心代码
    public void Subdivide_Click(object sender, RoutedEventArgs e)
    {
        // 算出了分割结果,要用m_SubdivPolygon的点代替m_Ploygon,同时还要清空m_SubdivPolygon
        if (m_IsSubdivided)
        {
            m_Ploygon.Points = m_SubdivPolygon.Points;
            m_SubdivPolygon.Points = new PointCollection();
        }

        int n = m_Ploygon.Points.Count;
        if (n > 0)
        {
            m_IsSubdivided = true;
            // 和算法无关
            m_DashLine.ClearValue(Line.X1Property);
            m_DashLine.ClearValue(Line.Y1Property);
            m_DashLine.ClearValue(Line.X2Property);
            m_DashLine.ClearValue(Line.Y2Property);
        }
        
        var points = m_Ploygon.Points;
        for (int i = 0; i < n; i++)
        {
            int nexti = (i + 1) % n; // 下一个点的索引
            int lasti = (i + (n - 1)) % n; // 上一个点的索引
            // |___|______|
            // A___B______C   已知A点和C点的坐标,则 B = (BC/AC)* A + (AB/AC) * C;
            double x = m_Weight * points[lasti].X + (1 - m_Weight) * points[i].X;
            double y = m_Weight * points[lasti].Y + (1 - m_Weight) * points[i].Y;
            m_SubdivPolygon.Points.Add(new Point(x, y));

            x = m_Weight * points[nexti].X + (1 - m_Weight) * points[i].X;
            y = m_Weight * points[nexti].Y + (1 - m_Weight) * points[i].Y;
            m_SubdivPolygon.Points.Add(new Point(x, y));
        }

        e.Handled = true; // don't propagate the click any further
    }
    
    public void Clear_Click(object sender, RoutedEventArgs e)
    {
        m_Ploygon.Points.Clear();
        m_SubdivPolygon.Points.Clear();
        m_DashLine.ClearValue(Line.X1Property);
        m_DashLine.ClearValue(Line.Y1Property);
        m_DashLine.ClearValue(Line.X2Property);
        m_DashLine.ClearValue(Line.Y2Property);
        m_IsSubdivided = false;

        e.Handled = true; // don't propagate the click any further
    }

    private void InitPoly(Polygon polygon, SolidColorBrush brush)
    {
        polygon.Stroke = brush;
        polygon.StrokeThickness = 0.5f;
        polygon.StrokeMiterLimit = 1; // 该系数是用于锐化拐角的长度和直线宽度的一半的比值
        polygon.Fill = null;
    }

    private void InitLine(Line line, SolidColorBrush brush)
    {
        line.Stroke = brush;
        line.StrokeThickness = 0.3;
        line.StrokeDashArray = new DoubleCollection() { 2, 1 };
        line.Fill = null;
    }
}

 

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像