cad.net 封装两个填充类

生成填充的类

渐变填充部分参考了才鸟的书里的代码,但是我改的也挺多的...

调用

namespace JoinBox
{
    public partial class CmdTest
    {
        /// <summary>
        /// 测试填充
        /// </summary>
        [CommandMethod("CmdTest_CreateHatch")]
        public void CmdTest_CreateHatch()
        {
            var dm = Acap.DocumentManager;
            var doc = dm.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            ed.WriteMessage($"{Environment.NewLine}测试填充生成");

            //选择已有的闭合多段线进行内部填充
            int actionNum = 2 | 4;
            if ((actionNum & 1) == 1)
            {
                var psr = ed.GetSelection();
                if (psr.Status != PromptStatus.OK)
                    return;
                db.Action(tr => {
                    new HatchInfo(psr.Value.GetObjectIds(), true, null, 100, 0)
                        .Mode1PreDefined("ANSI34")
                        .Build(tr, db);
                });
            }
            if ((actionNum & 2) == 2)
            {
                var psr = ed.GetSelection();
                if (psr.Status != PromptStatus.OK)
                    return;

                db.Action(tr => {
                    new HatchInfo(psr.Value.GetObjectIds(), true, null, 100, 0)
                        .Mode2UserDefined()
                        .Build(tr, db);
                });
            }

            if ((actionNum & 4) == 4)
            {
                var psr = ed.GetSelection();
                if (psr.Status != PromptStatus.OK)
                    return;

                db.Action(tr => {
                    new HatchInfo(psr.Value.GetObjectIds(), true, null, 100, Math.PI / 2)
                        .Mode4Gradient(HatchInfo.HatchGradientName.Linear,
                                       Autodesk.AutoCAD.Colors.Color.FromRgb(0, 0, 0),
                                       Autodesk.AutoCAD.Colors.Color.FromRgb(152, 35, 100))
                        .Build(tr, db);
                });
            }
        }
    }
}

封装

#if !HC2020
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Colors;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.Geometry;
using GrxCAD.Colors;
#endif
using System.Collections.Generic;
using System;

namespace JoinBox
{
    /*
     *  添加的第一个边界必须是外边界,即用于定义图案填充最外面的边界。
     *  要添加外部边界,请使用添加环的类型为 HatchLoopTypes.Outermost 常量的 AppendLoop 方法,
     *  一旦外边界被定义,就可以继续添加另外的边界。
     *  添加内部边界请使用带 HatchLoopTypes.Default 常量的 AppendLoop 方法。
     *
     *  多个外边界的时候,添加的是(外边界,外边界,外边界,普通边界....)
     *  多个外边界的时候,添加的是(外边界,普通边界.....外边界,普通边界....)
     */

    /// <summary>
    /// 图案填充
    /// </summary>
    public class HatchInfo
    {
        #region 成员
        /// <summary>
        /// 边界id(最外面放第一)
        /// </summary>
        List<ObjectId> _boundaryIds;
        /// <summary>
        /// 填充图元
        /// </summary>
        Hatch _hatch;
        /// <summary>
        /// 填充的名称:用户定义(固定名称)/渐变/填充依据定义文件
        /// </summary>
        string? _hatchName;
        /// <summary>
        /// 填充模式类型(预定义/用户定义/自定义)
        /// </summary>
        HatchPatternType _patternTypeHatch;
        /// <summary>
        /// 渐变模式类型
        /// </summary>
        GradientPatternType _patternTypeGradient;
        /// <summary>
        /// 比例/间距
        /// </summary>
        double _scale => _hatch.PatternScale;
        /// <summary>
        /// 角度
        /// </summary>
        double _angle => _hatch.PatternAngle;
        /// <summary>
        /// 边界关联(此处不能直接=>给填充成员,因为它会加入反应器)
        /// </summary>
        bool _boundaryAssociative;
        #endregion

        #region 构造
        HatchInfo()
        {
            _hatch = new Hatch();
            _hatch.SetDatabaseDefaults();
            _boundaryIds = new();
        }

        /// <summary>
        /// 图案填充
        /// </summary>
        /// <param name="boundaryAssociative">关联边界</param>
        /// <param name="hatchOrigin">填充原点</param>
        /// <param name="hatchScale">比例</param>
        /// <param name="hatchAngle">角度</param>
        public HatchInfo(bool boundaryAssociative = true,
                         Point2d? hatchOrigin = null,
                         double hatchScale = 1,
                         double hatchAngle = 0) : this()
        {
            if (hatchScale <= 0)
                throw new ArgumentException("填充比例不允许小于等于0");

            _hatch.PatternScale = hatchScale;//填充比例
            _hatch.PatternAngle = hatchAngle;//填充角度
            _boundaryAssociative = boundaryAssociative;

            hatchOrigin ??= Point2d.Origin;
            _hatch.Origin = hatchOrigin.Value; //填充原点
        }

        /// <summary>
        /// 图案填充
        /// </summary>
        /// <param name="boundaryIds">边界</param>
        /// <param name="boundaryAssociative">关联边界</param>
        /// <param name="hatchOrigin">填充原点</param>
        /// <param name="hatchScale">比例</param>
        /// <param name="hatchAngle">角度</param>
        public HatchInfo(IEnumerable<ObjectId> boundaryIds,
                         bool boundaryAssociative = true,
                         Point2d? hatchOrigin = null,
                         double hatchScale = 1,
                         double hatchAngle = 0)
            : this(boundaryAssociative, hatchOrigin, hatchScale, hatchAngle)
        {
            _boundaryIds.AddRange(boundaryIds);
        }

        #endregion

        #region 方法
        /// <summary>
        /// 模式1:预定义
        /// </summary>
        public HatchInfo Mode1PreDefined(string name)
        {
            _hatchName = name;
            _hatch.HatchObjectType = HatchObjectType.HatchObject; //对象类型(填充/渐变)
            _patternTypeHatch = HatchPatternType.PreDefined;
            return this;
        }

        /// <summary>
        /// 模式2:用户定义
        /// </summary>
        /// <param name="patternDouble">是否双向</param>
        public HatchInfo Mode2UserDefined(bool patternDouble = true)
        {
            _hatchName = "_USER";
            _hatch.HatchObjectType = HatchObjectType.HatchObject; //对象类型(填充/渐变)
            _patternTypeHatch = HatchPatternType.UserDefined;

            _hatch.PatternDouble = patternDouble; //是否双向(必须写在 SetHatchPattern 之前)
            _hatch.PatternSpace = _scale;         //间距(必须写在 SetHatchPattern 之前)
            return this;
        }

        /// <summary>
        /// 模式3:自定义
        /// </summary>
        /// <param name="name"></param>
        public HatchInfo Mode3UserDefined(string name)
        {
            _hatchName = name;
            _hatch.HatchObjectType = HatchObjectType.HatchObject; //对象类型(填充/渐变)
            _patternTypeHatch = HatchPatternType.CustomDefined;
            return this;
        }

        /// <summary>
        /// 模式4:渐变填充
        /// </summary>
        /// <param name="name">渐变填充名称</param>
        /// <param name="colorStart">渐变色起始颜色</param>
        /// <param name="colorEnd">渐变色结束颜色</param>
        /// <param name="gradientShift">渐变移动</param>
        /// <param name="shadeTintValue">色调值</param>
        /// <param name="gradientOneColorMode">单色<see langword="true"/>双色<see langword="false"/></param>
        public HatchInfo Mode4Gradient(GradientName name, Color colorStart, Color colorEnd,
            float gradientShift = 0,
            float shadeTintValue = 0,
            bool gradientOneColorMode = false)
        {
            //entget渐变的名字必然是"SOLID",但是这里作为"渐变"名,而不是"填充"名
            _hatchName = name.ToString();
            _hatch.HatchObjectType = HatchObjectType.GradientObject;      //对象类型(填充/渐变)
            _patternTypeGradient = GradientPatternType.PreDefinedGradient;//模式4:渐变
            //_patternTypeGradient = GradientPatternType.UserDefinedGradient;//模式5:渐变..这种模式干啥用呢

            //设置渐变色填充的起始和结束颜色
            var gColor1 = new GradientColor(colorStart, 0);
            var gColor2 = new GradientColor(colorEnd, 1);
            _hatch.SetGradientColors(new GradientColor[] { gColor1, gColor2 });

            _hatch.GradientShift = gradientShift;              //梯度位移
            _hatch.ShadeTintValue = shadeTintValue;            //阴影色值
            _hatch.GradientOneColorMode = gradientOneColorMode;//渐变单色/双色
            _hatch.GradientAngle = _angle;                     //渐变角度

            return this;
        }

        /// <summary>
        /// 构建
        /// </summary>
        /// <param name="tr">事务</param>
        /// <param name="db">数据库</param>
        public ObjectId Build(Transaction tr, Database db)
        {
            //加入数据库
            var hatchId = tr.AddEntityToMsPs(db, _hatch);

            //设置模式:渐变/填充
            if (_hatch.HatchObjectType == HatchObjectType.GradientObject)
                _hatch.SetGradient(_patternTypeGradient, _hatchName);
            else
                _hatch.SetHatchPattern(_patternTypeHatch, _hatchName);

            //关联边界,如果不先添加数据库空间内就会出错
            //为 true 会加入反应器,因此比较慢(二维码将会十几秒才生成好),视需求而定.
            _hatch.Associative = _boundaryAssociative;

            //利用 AppendLoop 重载加入,这里就不处理
            if (_boundaryIds.Count > 0)
                AppendLoop(_boundaryIds, HatchLoopTypes.Default);

            //计算填充并显示(若边界出错,这句会异常)
            _hatch.EvaluateHatch(true);

            return hatchId;
        }

        /// <summary>
        /// 执行图元的属性修改
        /// </summary>
        /// <param name="action">扔出填充实体</param>
        public HatchInfo Action(Action<Hatch> action)
        {
            action(_hatch);
            return this;
        }

        /// <summary>
        /// 清空边界集合
        /// </summary>
        public HatchInfo ClearBoundary()
        {
            _boundaryIds.Clear();
            return this;
        }

        /// <summary>
        /// 删除边界图元
        /// </summary>
        public HatchInfo EraseBoundary(Transaction tr)
        {
            tr.EntityErase(_boundaryIds);
            return this;
        }

        /// <summary>
        /// 加入边界
        /// </summary>
        /// <param name="boundaryIds">边界id</param>
        /// <param name="hatchLoopTypes">加入方式</param>
        /// <returns></returns>
        void AppendLoop(IEnumerable<ObjectId> boundaryIds,
                             HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default)
        {
            var obIds = new ObjectIdCollection();
            //边界是闭合的,而且已经加入数据库
            //填充闭合环类型.最外面
            foreach (var border in boundaryIds)
            {
                obIds.Clear();
                obIds.Add(border);
                _hatch.AppendLoop(hatchLoopTypes, obIds.Collection);
            }
            obIds.Dispose();
        }

        /// <summary>
        /// 加入边界(仿高版本的填充函数)
        /// </summary>
        /// <param name="pts">点集</param>
        /// <param name="bluges">凸度集</param>
        /// <param name="tr">事务</param>
        /// <param name="db">数据库</param>
        /// <param name="hatchLoopTypes">加入方式</param>
        /// <returns></returns>
        public HatchInfo AppendLoop(Point2dCollection pts, DoubleCollection bluges,
                                    Transaction tr, Database db,
                                    HatchLoopTypes hatchLoopTypes = HatchLoopTypes.Default)
        {
            //创建边界,之后再 Build
            if (pts == null)
                throw new ArgumentNullException(nameof(pts));
            var ptsEnd2End = pts.End2End();
#if NET35
            _boundaryIds.Add(CreateAddBoundary(ptsEnd2End, bluges, tr, db));
#else
            //2011新增API,可以不生成图元的情况下加入边界,
            //通过这里进入的话,边界 _boundaryIds 是空的,那么 Build() 时候就需要过滤空的
            if (ptsEnd2End is not null)
                _hatch.AppendLoop(hatchLoopTypes, ptsEnd2End.Collection, bluges.Collection);
#endif
            return this;
        }

        /// <summary>
        /// 通过点集和凸度生成多段线边界
        /// </summary>
        /// <param name="pts">点集</param>
        /// <param name="bluges">凸度集</param>
        /// <param name="tr">事务</param>
        /// <param name="db">数据库</param>
        /// <returns>多段线id</returns>
        static ObjectId CreateAddBoundary(Point2dCollection? pts, DoubleCollection? bluges,
                                   Transaction tr, Database db)
        {
            if (pts is null)
                throw new ArgumentException(null, nameof(pts));
            if (bluges is null)
                throw new ArgumentException(null, nameof(bluges));

            var bvws = new List<BulgeVertexWidth>();

            var itor1 = pts.GetEnumerator();
            var itor2 = bluges.GetEnumerator();
            while (itor1.MoveNext() && itor2.MoveNext())
                bvws.Add(new BulgeVertexWidth(itor1.Current, itor2.Current));

            return tr.AddEntityToMsPs(db, EntityAdd.AddPolyLineToEntity(bvws));
        }
        #endregion

        #region 枚举
        /// <summary>
        /// 渐变色填充的图案名称
        /// </summary>
        public enum GradientName
        {
            /// <summary>
            /// 线状渐变
            /// </summary>
            Linear,
            /// <summary>
            /// 圆柱状渐变
            /// </summary>
            Cylinder,
            /// <summary>
            /// 反圆柱状渐变
            /// </summary>
            Invcylinder,
            /// <summary>
            /// 球状渐变
            /// </summary>
            Spherical,
            /// <summary>
            /// 反球状渐变
            /// </summary>
            Invspherical,
            /// <summary>
            /// 半球状渐变
            /// </summary>
            Hemisperical,
            /// <summary>
            /// 反半球状渐变
            /// </summary>
            InvHemisperical,
            /// <summary>
            /// 抛物面状渐变
            /// </summary>
            Curved,
            /// <summary>
            /// 反抛物面状渐变
            /// </summary>
            Incurved
        }
        #endregion
    }
}

生成填充边界的类

有一些顾名思义的函数,基本上博客搜索一下都有,
搜索时候用 public BulgeVertexWidth 就可以搜到构造函数,而不是调用.

没有就自己写,毕竟看到这里的都是高手了.
比较特别的是调用了IFox的ToCurve函数

这个类测试得不是很全面,可能存在bug..

闲逛明经发现飞狐也写过,只是他是生成原线 http://bbs.mjtd.com/thread-75636-1-1.html

调用

/// <summary>
/// 测试填充边界生成
/// </summary>
[CommandMethod("CmdTest_HatchConverter")]
public void CmdTest_HatchConverter()
{
    var dm = Acap.DocumentManager;
    var doc = dm.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;
    ed.WriteMessage($"{Environment.NewLine}测试填充边界生成");

    var ids = ed.Ssget();
    List<ObjectId> boIds = new();

    db.Action(tr => {
        ids.ToEntity(tr, ent => {
            if (ent is Hatch hatch)
            {
                var hc = new HatchConverter(hatch);
                var newHatchId = hc.CreateBoundarysAndHatchToMsPs(tr, db, true, true/*设置false就是只创建边界*/);
                var bos = hc.BoundaryIds;
            }
        });
    });
}

封装

#if !HC2020
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
#else
using GrxCAD.DatabaseServices;
using GrxCAD.Geometry;
#endif

using System;
using System.Collections.Generic;

using IFoxCAD.Cad;
using JoinBox.BasalMath;
using static JoinBox.EntityAdd;
using System.Diagnostics;

namespace JoinBox
{
    public class HatchConverter
    {
        #region 辅助类
        /// <summary>
        /// 生成圆形数据
        /// </summary>
        class CircleData
        {
            public PointV Center;
            public double Radius;

            /// <summary>
            /// 生成圆形数据
            /// </summary>
            /// <param name="symmetryAxisPoint1">对称点1</param>
            /// <param name="symmetryAxisPoint2">对称点2</param>
            public CircleData(PointV symmetryAxisPoint1, PointV symmetryAxisPoint2)
            {
                Center = symmetryAxisPoint1.GetCenter(symmetryAxisPoint2);
                Radius = symmetryAxisPoint1.GetDistanceTo(symmetryAxisPoint2) / 2;
            }
        }

        /// <summary>
        /// 填充转换器的数据
        /// </summary>
        class HatchConverterData
        {
            public List<BulgeVertexWidth> PolyLineData;
            public List<CircleData> CircleData;
            public List<NurbCurve2d> SplineData;

            /// <summary>
            /// 填充转换器的数据
            /// </summary>
            public HatchConverterData()
            {
                PolyLineData = new();
                CircleData = new();
                SplineData = new();
            }
        }
        #endregion

        #region 成员
        /// <summary>
        /// 外部只能调用id,否则跨事务造成错误
        /// </summary>
        public ObjectId OldHatchId
        {
            get
            {
                if (_oldHatch is null)
                    return ObjectId.Null;
                return _oldHatch.ObjectId;
            }
        }
        readonly Hatch? _oldHatch;

        readonly List<HatchConverterData> _hcDatas;
        /// <summary>
        /// 生成的填充边界id
        /// </summary>
        public List<ObjectId> BoundaryIds;
        #endregion

        #region 构造
        /// <summary>
        /// 填充边界转换器
        /// </summary>
        HatchConverter()
        {
            _hcDatas = new();
            BoundaryIds = new();
        }

        /// <summary>
        /// 填充边界转换器
        /// </summary>
        /// <param name="hatch">需要转化的Hatch对象</param>
        public HatchConverter(Hatch hatch) : this()
        {
            _oldHatch = hatch;

            //不能在提取信息的时候进行新建cad图元,
            //否则cad将会提示遗忘释放
            hatch.ForEach(loop => {
                var hcData = new HatchConverterData();

                bool isCurve2d = true;
                if (loop.IsPolyline)
                {
                    //边界是多段线
                    HatchLoopIsPolyline(loop, hcData);
                    isCurve2d = false;
                }
                else
                {
                    if (loop.Curves.Count == 2)//1是不可能的,大于2的是曲线
                    {
                        //边界是曲线,过滤可能是圆形的情况
                        var cir = TwoArcFormOneCircle(loop);
                        if (cir is not null)
                        {
                            hcData.CircleData.Add(cir);
                            isCurve2d = false;
                        }
                    }
                }

                //边界是曲线
                if (isCurve2d)
                    HatchConverter.HatchLoopIsCurve2d(loop, hcData);

                _hcDatas.Add(hcData);
            });
        }
        #endregion

        #region 方法
        /// <summary>
        /// 多段线处理
        /// </summary>
        /// <param name="loop">填充边界</param>
        /// <param name="hcData">收集图元信息</param>
        static void HatchLoopIsPolyline(HatchLoop loop, HatchConverterData hcData)
        {
            if (loop is null)
                throw new ArgumentNullException(nameof(loop));

            if (hcData is null)
                throw new ArgumentNullException(nameof(hcData));

            //判断为圆形:
            //上下两个圆弧,然后填充,就会生成此种填充
            //顶点数是3,凸度是半圆,两个半圆就是一个圆形
            if (loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == 1 && loop.Polyline[1].Bulge == 1 ||
                loop.Polyline.Count == 3 && loop.Polyline[0].Bulge == -1 && loop.Polyline[1].Bulge == -1)
            {
                hcData.CircleData.Add(new CircleData(loop.Polyline[0].Vertex, loop.Polyline[1].Vertex));
            }
            else
            {
                //遍历多段线信息
                var bvc = loop.Polyline;
                for (int i = 0; i < bvc.Count; i++)
                    hcData.PolyLineData.Add(new BulgeVertexWidth(bvc[i]));
            }
        }

        /// <summary>
        /// 两个圆弧组成圆形
        /// </summary>
        /// <param name="loop"></param>
        /// <returns></returns>
        static CircleData? TwoArcFormOneCircle(HatchLoop loop)
        {
            if (loop is null)
                throw new ArgumentNullException(nameof(loop));

            if (loop.Curves.Count != 2)
                throw new ArgumentException(
                    "边界非多段线,而且点数!=2,点数为:" + nameof(loop.Curves.Count) + ";两个矩形交集的时候会出现此情况.");

            CircleData? circular = null;

            //判断为圆形:
            //用一条(不是两条)多段线画出两条圆弧为正圆,就会生成此种填充
            //边界为曲线,数量为2,可能是两个半圆曲线,如果是,就加入圆形数据中

            //第一段
            var getCurves1Pts = loop.Curves[0].GetSamplePoints(3);   //曲线取样点分两份(3点)
            var mid1Pt = getCurves1Pts[1];                           //腰点
            double bulge1 = MathHelper.GetArcBulge(
                loop.Curves[0].StartPoint, mid1Pt, loop.Curves[0].EndPoint);

            //第二段
            var getCurves2Pts = loop.Curves[1].GetSamplePoints(3);
            var mid2Pt = getCurves2Pts[1];
            double bulge2 = MathHelper.GetArcBulge(
                loop.Curves[1].StartPoint, mid2Pt, loop.Curves[1].EndPoint);

            //第一段上弧&&第二段反弧 || 第一段反弧&&第二段上弧
            if (bulge1 == -1 && bulge2 == -1 || bulge1 == 1 && bulge2 == 1)
                circular = new CircleData(loop.Curves[0].StartPoint, loop.Curves[1].StartPoint); //两个起点就是对称点

            return circular;
        }

        /// <summary>
        /// 处理边界曲线
        /// </summary>
        /// <param name="loop">填充边界</param>
        /// <param name="hcData">收集图元信息</param>
        static void HatchLoopIsCurve2d(HatchLoop loop, HatchConverterData hcData)
        {
            //取每一段曲线,曲线可能是直线来的,但是圆弧会按照顶点来分段
            int curveIsClosed = 0;

            //遍历边界的多个子段
            foreach (Curve2d curve in loop.Curves)
            {
                //计数用于实现闭合
                curveIsClosed++;
                if (curve is NurbCurve2d spl)
                {
                    //判断为样条曲线:
                    hcData.SplineData.Add(spl);
                    continue;
                }

                var pts = curve.GetSamplePoints(3);
                var midPt = pts[1];
                if (curve.StartPoint.IsEqualTo(curve.EndPoint, MathHelper.Tolerance))//首尾相同,就是圆形
                {
                    //判断为圆形:
                    //获取起点,然后采样三点,中间就是对称点(直径点)
                    hcData.CircleData.Add(new CircleData(curve.StartPoint, midPt));
                    continue;
                }

                //判断为多段线,圆弧:
                double bulge = MathHelper.GetArcBulge(curve.StartPoint, midPt, curve.EndPoint);
                hcData.PolyLineData.Add(new BulgeVertexWidth(curve.StartPoint, bulge));

                //末尾点,不闭合的情况下就要获取这个
                if (curveIsClosed == loop.Curves.Count)
                    hcData.PolyLineData.Add(new BulgeVertexWidth(curve.EndPoint, 0));
            }
        }

        /// <summary>
        /// 创建边界图元到当前空间
        /// </summary>
        /// <param name="tr"></param>
        /// <param name="db"></param>
        /// <returns>边界在<see cref="BoundaryIds"/>获取</returns>
        void CreateBoundarysToMsPs(Transaction tr, Database db)
        {
            var ents = new List<Entity>();

            for (int i = 0; i < _hcDatas.Count; i++)
            {
                var info = _hcDatas[i];

                //生成边界:多段线
                if (info.PolyLineData.Count > 0)
                {
                    var ent = AddPolyLineToEntity(info.PolyLineData);
                    ents.Add(ent);
                }

                //生成边界:圆
                info.CircleData.ForEach(item => {
                    var ent = AddCircleToEntity(item.Center.ToPoint3d(), item.Radius);
                    ents.Add(ent);
                });

                //生成边界:样条曲线
                info.SplineData.ForEach(item => {
                    var ent = item.ToCurve();
                    ents.Add(ent);
                });
            }

            ents.ForEach(ent => {
                if (_oldHatch is not null)
                {
                    ent.Color = _oldHatch.Color;
                    ent.Layer = _oldHatch.Layer;
                }
                BoundaryIds.Add(tr.AddEntityToMsPs(db, ent));
            });
        }

        /// <summary>
        /// 创建边界图元和新填充到当前空间
        /// </summary>
        /// <param name="tr">事务</param>
        /// <param name="db">数据库</param>
        /// <param name="boundaryAssociative">边界关联</param>
        /// <param name="createHatchFlag">是否创建填充,false则只创建边界</param>
        /// <returns>新填充id,边界在<see cref="BoundaryIds"/>获取</returns>
        public ObjectId CreateBoundarysAndHatchToMsPs(Transaction tr, Database db,
            bool boundaryAssociative = true,
            bool createHatchFlag = true)
        {
            CreateBoundarysToMsPs(tr, db);

            if (!createHatchFlag)
                return ObjectId.Null;

            /*
             * 此处为什么要克隆填充,而不是新建填充?
             * 因为填充如果是新建的,那么将会丢失基点,概念如下:
             * 两个一样的填充,平移其中一个,那么再提取他们的基点会是一样的!
             * 所以生成时候就不等同于画面相同.
             * 也因为我不知道什么新建方式可以新建一模一样的填充,因此使用了克隆
             * 那么它的平移后的基点在哪里呢?
             */
            var newHatch = tr.EntityClone(OldHatchId.ToArray())[0];
            newHatch.ToEntity(tr, ent => {
                ResetBoundary((Hatch)ent, boundaryAssociative);
            });
            return newHatch;
        }


        /// <summary>
        /// 重设边界
        /// </summary>
        /// <param name="hatch"></param>
        /// <param name="boundaryAssociative">边界关联</param>
        void ResetBoundary(Hatch hatch,
            bool boundaryAssociative = true)
        { 
            //删除原有边界
            while (hatch.NumberOfLoops != 0)
                hatch.RemoveLoopAt(0);

            hatch.Associative = boundaryAssociative;

            var obIds = new ObjectIdCollection();
            for (int i = 0; i < BoundaryIds.Count; i++)
            {
                obIds.Clear();
                obIds.Add(BoundaryIds[i]);
                //要先添加最外面的边界
                if (i == 0)
                    hatch.AppendLoop(HatchLoopTypes.Outermost, obIds.Collection);
                else
                    hatch.AppendLoop(HatchLoopTypes.Default, obIds.Collection);
            }
            //计算填充并显示
            hatch.EvaluateHatch(true);
        }
        #endregion
    }
}

补充End2End

public static partial class PointEx
{
    #region 首尾相连
    /// <summary>
    /// 首尾相连
    /// </summary>
    public static Point2dCollection End2End(this Point2dCollection ptcol!!)
    {
        if (ptcol.Count == 0 || ptcol[0].Equals(ptcol[^1]))//首尾相同直接返回
            return ptcol;

        //首尾不同,去加一个到最后
        var lst = new Point2d[ptcol.Count + 1];
        for (int i = 0; i < lst.Length; i++)
            lst[i] = ptcol[i];
        lst[^1] = lst[0];

        return new(lst);
    }
    /// <summary>
    /// 首尾相连
    /// </summary>
    public static Point3dCollection End2End(this Point3dCollection ptcol!!)
    {
        if (ptcol.Count == 0 || ptcol[0].Equals(ptcol[^1]))//首尾相同直接返回
            return ptcol;

        //首尾不同,去加一个到最后
        var lst = new Point3d[ptcol.Count + 1];
        for (int i = 0; i < lst.Length; i++)
            lst[i] = ptcol[i];
        lst[^1] = lst[0];

        return new(lst);
    }
    #endregion
}

(完)

posted @ 2022-01-18 22:55  惊惊  阅读(918)  评论(0编辑  收藏  举报