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
}

(完)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM