技术支持 / 技术论坛 / 二次开发 / 【技术分享】【C#】用clipper实现多边形偏置
【技术分享】【C#】用clipper实现多边形偏置
freeter
帖子
1
精华
0
积分
12
二次开发 技术分享

    Clipper库是一个开源的C++库,专门用于线段和多边形的裁剪以及偏置计算。它提供了一套简单易用的API,允许开发人员快速地创建复杂的裁剪和偏置算法。参考链接:https://www.cnblogs.com/zhigu/p/11943118.html

    1.导入clpper库

    2.编写相关类

    由于clipper采用的是整型数据,可以通过适当的缩放数据来计算。同时指出Clipper库能接受范围为(4.6+18)的整数坐标值,支持扩展到非常高的精度。这说明我们可以放心得对极小数值进行较大倍数的缩放,不会造成算法的问题,类里采用的精度是1000。

    /// <summary>
    /// 偏置多边形(clipper)
    /// </summary>
    internal class OffsetPolygon
    {
        /// <summary>
        /// clipper中的路径
        /// </summary>
        internal List<IntPoint> Path { set; get; }=new List<IntPoint>();

        /// <summary>
        /// 偏置距离
        /// </summary>
        internal double OffsetDistance { set; get; }

        /// <summary>
        /// 精度
        /// </summary>
        internal double ClipperScale { set; get; } = 1000;

        internal OffsetPolygon(List<Point3> point3S, double offsetDistance)
        {
            for (int i = 0; i < point3S.Count; i++)
            {
                var x = Math.Round(point3S[i].X, 3) * 1000;
                var y = Math.Round(point3S[i].Y, 3) * 1000;
                this.Path.Add(new IntPoint(x,y));
            }
            this.OffsetDistance = offsetDistance;
        }


        internal List<IntPoint> Commit()
        {
            int miterLimit = 2;
            ClipperOffset co = new ClipperOffset(miterLimit); //向ClipperOffset对象添加一个路径用来准备偏置
            co.AddPath(Path, JoinType.jtRound, EndType.etClosedPolygon);
            List<List<IntPoint>> paths=new List<List<IntPoint>>();
            co.Execute(ref paths,this.OffsetDistance*1000);
            var offsetPath = paths.First();
            return offsetPath;
        }

    3.使用类

                    var discretePointList = GetSelectFacePointSet(selectFace); //获取多边形点集
                    var cSys = selectFace.AskFaceData().Direction.InitializeZ(selectFace.AskFaceData().Point); 
                    discretePointList =discretePointList.Select(a => a.ToWcs(cSys)).ToList(); //点集转换(转换成所在平面的坐标)

                    OffsetPolygon offsetPolygon=new OffsetPolygon(discretePointList,2); //实例偏置类
                    var offsetIntPoints = offsetPolygon.Commit();
                    var offsetPoint3S = offsetIntPoints.Select(a => new Point3((double)a.X / 1000, (double)a.Y / 1000)).ToList();

                    //相对坐标转回去
                    theUfSession.Csys.SetWcs(cSys.Create().Tag);
                    int inputCSys = UFConstants.UF_CSYS_ROOT_WCS_COORDS;
                    int outputCSys = UFConstants.UF_CSYS_ROOT_COORDS;
                    List<Point3> targetPoint3S=new List<Point3>();
                    for (int i = 0; i < offsetPoint3S.Count; i++)
                    {
                        Point3 outputPoint = new Point3();
                        theUfSession.Csys.MapPoint(inputCSys,offsetPoint3S[i],outputCSys,outputPoint);
                        targetPoint3S.Add(outputPoint);
                    }

                    //临时线绘制
                    for (int i = 0; i < targetPoint3S.Count; i++)
                    {
                        CreateTempLine(targetPoint3S[i],targetPoint3S[(i+1)%targetPoint3S.Count]); 
                    }

效果图:


740 0 2023-12-27 17:59:26
暂时还没有回复评论

回复加入讨论

回复
请选择移动至版块:
确认移动