cad.net 替换轻多段线和复杂实体的点+二度封装Collection类

轻多段线与复杂实体

Polyline是轻多段线

Polyline2dPolyline3dPolyFaceMesh多面网格 等等这些是复杂实体,它们需要通过迭代器处理.

获取点集

先看一个通用的提取点集的做法,主要目的是针对轻多段线/二维多段线/三维多段线.

public static partial class EntityEdit
{
    /// <summary>
    /// 图元拉伸点
    /// </summary>
    /// <param name="ent"></param>
    /// <returns></returns>
    public static List<Point3d> GetEntityPoint3ds(this Entity ent)
    {
        var pts3d = new Point3dCollection();
        ent.GetStretchPoints(pts3d.Collection);
        return pts3d.ToList();
    }

    /// <summary>
    /// 获取轻多段线顶点和凸度
    /// </summary>
    /// <param name="pl"></param>
    /// <returns></returns>
    public static List<BulgeVertexWidth> GetBulgeVertexWidth(this Polyline pl)
    {
        var lst = new List<BulgeVertexWidth>();
        for (int i = 0; i < pl.NumberOfVertices; i++)
            lst.Add(new BulgeVertexWidth()
                    {
                        Vertex     = pl.GetPoint2dAt(i),//这里可以3d
                        Bulge      = pl.GetBulgeAt(i),
                        StartWidth = pl.GetStartWidthAt(i),
                        EndWidth   = pl.GetEndWidthAt(i),
                    });
        return lst;
    } 
}

设置点集

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

namespace JoinBox
{
    //模板类<子图元,可枚举的复合图元>
    public class SetPts<TEntityItem, TEntity>
        where TEntityItem : Vertex
        where TEntity : Entity, IEnumerable
    {
        public SetPts(TEntity ent, Point3d[] pts)
        {
            //补充点,再修改,再删除多余点????这里似乎做不到呀

            var position = typeof(TEntityItem).GetMethod("Position");
            if(position == null)
                return;

            int i = 0;
            foreach (TEntityItem ver in ent)
            {
                if (i < pts.Length)
                {
                    ver.UpgradeOpen();
                    //头改到尾 ver.Position = pts[i++];
                    //ver.GetType().GetMethod("Position").Invoke(ver, new object[] { pts[i++] });//这句能用吗?
                    position.Invoke(ver, new object[] { pts[i++] });
                    ver.DowngradeOpen();
                    ver.Dispose();
                }
            }
        }
    }

    public static partial class EntityEdit
    {
        /// <summary>
        /// 设置点集
        /// </summary>
        /// <param name="ent">多面网格</param>
        /// <param name="pts"></param>
        public static void SetPts(this PolyFaceMesh ent, Point3d[] pts)
        {
            new SetPts<PolyFaceMeshVertex, PolyFaceMesh>(ent, pts);
        }

        /// <summary>
        /// 设置点集
        /// </summary>
        /// <param name="ent">三维多段线</param>
        /// <param name="pts"></param>
        public static void SetPts(this Polyline3d ent, Point3d[] pts)
        {
            new SetPts<PolylineVertex3d, Polyline3d>(ent, pts);
        }

        /// <summary>
        /// 设置点集
        /// </summary>
        /// <param name="ent">二维多段线</param>
        /// <param name="pts"></param>
        public static void SetPts(this Polyline2d ent, Point3d[] pts)
        {
            new SetPts<Vertex2d, Polyline2d>(ent, pts);
        }

        /// <summary>
        /// 替换Polyline2d顶点到逆时针
        /// </summary>
        /// <param name="pl2d"></param>
        public static void PtsToAclockwise(Polyline2d pl2d)
        {
            var pts = pl2d.GetEntityPoint3ds();
            if (pts.Count < 3)
                throw new ArgumentNullException("PtsToAclockwise点集少于3");

            //逆时针结束
            if (MathHelper.CrossAclockwise(pts[0], pts[1], pts[2]))
                return;
            //将点集改为逆时针:
            //(虽然先加入再移除可能触发集合扩容,但插入到头部必然出现item移动一次,加上逆转又一次,所以应该放在随机上)
            //[1 2 3 4] => [1 2 3 4 1] => [1 4 3 2 1] => [1 4 3 2]
            pts.Add(pts[0]);
            pts.Reverse();
            pts.RemoveAt(pts.Count - 1);
            pl2d.SetPts(pts.ToArray());
        }

        /// <summary>
        /// 设置点集
        /// </summary>
        /// <param name="ent">轻多段线</param>
        /// <param name="pts"></param>
        public static void SetPts(this Polyline ent, BulgeVertexWidth[] pts)
        {
#if false   //会引起ctrl+u回退不了
            polyline.Reset(false, 0);
            for (int i = 0; i < plPt.Length; i++)
            {
                polyline.AddVertexAt(i,
                    plPt[i].Vertex,
                    plPt[i].Bulge,
                    plPt[i].StartWidth,
                    plPt[i].EndWidth);
            }
#else
            //1.补充点
            for (int i = ent.NumberOfVertices; i < pts.Length; i++)
                ent.AddVertexAt(i, Point2d.Origin, 0, 0, 0);

            //2.修改点
            for (int i = 0; i < pts.Length; i++)
            {
                var en = pts[i];
                ent.SetPointAt(i, en.Vertex);
                ent.SetBulgeAt(i, en.Bulge);
                ent.SetStartWidthAt(i, en.StartWidth);
                ent.SetEndWidthAt(i, en.EndWidth);
            }

            //3.删除多余点
            var nv = ent.NumberOfVertices - pts.Length;
            for (int i = 0; i < nv; i++)
                ent.RemoveVertexAt(ent.NumberOfVertices - 1); //从末尾移除
#endif
        }
    }
}

子函数

MathHelper.CrossAclockwise 参考本博客二维叉乘求方向

多段线数据类

/// <summary>
/// 多段线的顶点,凸度,头宽,尾宽
/// </summary>
public class BulgeVertexWidth
{
    public Point2d Vertex { get; set; }
    public double Bulge { get; set; }
    public double StartWidth { get; set; }
    public double EndWidth { get; set; }

    public BulgeVertexWidth() { }
    public BulgeVertexWidth(Point2d vertex, double bulge, double startWidth = 0, double endWidth = 0)
    {
        Vertex     = vertex;
        Bulge      = bulge;
        StartWidth = startWidth;
        EndWidth   = endWidth;
    }
    public BulgeVertexWidth(BulgeVertex bv)
    {
        Vertex = bv.Vertex;
        Bulge  = bv.Bulge;
    }
    public BulgeVertex ToBulgeVertex()
    {
        return new BulgeVertex(Vertex, Bulge);
    }
}

二度封装Collection类

您是否因为Point3dCollection的foreach的var不能自举类型而烦恼?那就来做这个操作吧!
我做了如下操作:

  1. 覆盖同名函数Point3dCollection,就是命名空间是自己的,而类型名是这个,这样你就不需要大改其他位置的代码了.
  2. 制作迭代器代替一次封装的迭代器,以自举Point3d出来

Collection.cs 调用

using Autodesk.AutoCAD.Geometry;
using System.Collections.Generic;

namespace JoinBox
{
    // 在这里全部加上迭代器自举类型
    public class Point2dCollection :
    JCollection<Point2d, Autodesk.AutoCAD.Geometry.Point2dCollection>
    {
        public Point2dCollection() : base()
        {
        }
        public Point2dCollection(IEnumerable<Point2d> pts) : base(pts)
        {
        }
        public Point2dCollection(Autodesk.AutoCAD.Geometry.Point2dCollection pts) : base(pts)
        {
        }

        // 隐式转换(相当于是重载赋值运算符)
        public static implicit operator Point2dCollection(Autodesk.AutoCAD.Geometry.Point2dCollection pts)
        {
            return new Point2dCollection(pts);
        }
    }

    public class Point3dCollection :
    JCollection<Point3d, Autodesk.AutoCAD.Geometry.Point3dCollection>
    {
        public Point3dCollection() : base()
        {
        }
        public Point3dCollection(IEnumerable<Point3d> pts) : base(pts)
        {
        }
        public Point3dCollection(Autodesk.AutoCAD.Geometry.Point3dCollection pts) : base(pts)
        {
        }

        // 隐式转换(相当于是重载赋值运算符)
        public static implicit operator Point3dCollection(Autodesk.AutoCAD.Geometry.Point3dCollection pts)
        {
            return new Point3dCollection(pts);
        }
    }

    public class DoubleCollection :
    JCollection<double, Autodesk.AutoCAD.Geometry.DoubleCollection>
    {
        public DoubleCollection() : base()
        {
        }
        public DoubleCollection(IEnumerable<double> dcs) : base(dcs)
        {
        }
        public DoubleCollection(Autodesk.AutoCAD.Geometry.DoubleCollection dcs) : base(dcs)
        {
        }

        // 隐式转换(相当于是重载赋值运算符)
        public static implicit operator DoubleCollection(Autodesk.AutoCAD.Geometry.DoubleCollection dcs)
        {
            return new DoubleCollection(dcs);
        }
    }


    public class Vector2dCollection :
    JCollection<Vector3d, Autodesk.AutoCAD.Geometry.Vector2dCollection>
    {
        public Vector2dCollection() : base()
        {
        }
        public Vector2dCollection(IEnumerable<Vector3d> vs) : base(vs)
        {
        }
        public Vector2dCollection(Autodesk.AutoCAD.Geometry.Vector2dCollection vs) : base(vs)
        {
        }

        // 隐式转换(相当于是重载赋值运算符)
        public static implicit operator Vector2dCollection(Autodesk.AutoCAD.Geometry.Vector2dCollection vs)
        {
            return new Vector2dCollection(vs);
        }
    }

    public class Vector3dCollection :
    JCollection<Vector3d, Autodesk.AutoCAD.Geometry.Vector3dCollection>
    {
        public Vector3dCollection() : base()
        {
        }
        public Vector3dCollection(IEnumerable<Vector3d> vs) : base(vs)
        {
        }
        public Vector3dCollection(Autodesk.AutoCAD.Geometry.Vector3dCollection vs) : base(vs)
        {
        }

        // 隐式转换(相当于是重载赋值运算符)
        public static implicit operator Vector3dCollection(Autodesk.AutoCAD.Geometry.Vector3dCollection vs)
        {
            return new Vector3dCollection(vs);
        }
    }
}

JCollection.cs 模板类

using System;
using System.Collections;
using System.Collections.Generic;
using JoinBox.BasalCurrency;

namespace JoinBox
{
    //在原有的基础上面附着迭代器
    public class JCollection<T, TCollection> : IEnumerable, IDisposable
        where TCollection : IList, new()
    {
        public TCollection Collection { get; private set; }

        /// <summary>
        /// 集合类模板
        /// </summary>
        public JCollection()
        {
            Collection = new TCollection();
        }

        public JCollection(TCollection ptc) : this()
        {
            Collection = ptc;
        }

        public JCollection(IEnumerable<T> ptc) : this()
        {
            foreach (var item in ptc)
                Collection.Add(item);
        }

        public T[] ToArray()
        {
            var ls = new T[Collection.Count];
            Collection.CopyTo(ls, 0);
            return ls;
        }

        public List<T> ToList()
        {
            var ls = new List<T>();
            var ge = Collection.GetEnumerator();
            while (ge.MoveNext())
                ls.Add((T)ge.Current);
            return ls;
        }

        public int Count { get => Collection.Count; }

        //迭代接口IEnumerable:支持foreach,支持var object
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        //约束函数名定义(接口并不强制此处),这里T控制了foreach的var自举类型
        public PublicEnumerator<T> GetEnumerator()
        {
            return new PublicEnumerator<T>(ToArray());
        }

        public void Add(T Point3d)
        {
            Collection.Add(Point3d);
        }

        public T this[int index]
        {
            get
            {
                return (T)Collection[index];
            }
            set
            {
                Collection[index] = value;
            }
        }

        public void Clear()
        {
            Collection.Clear();
        }

        #region Dispose
        public bool Disposed = false;

        /// <summary>
        /// 显式调用Dispose方法,继承IDisposable
        /// </summary>
        public void Dispose()
        {
            //由手动释放
            Dispose(true);
            //通知垃圾回收机制不再调用终结器(析构器)_跑了这里就不会跑析构函数了
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 析构函数,以备忘记了显式调用Dispose方法
        /// </summary>
        ~JCollection()
        {
            Dispose(false); //由系统释放
        }

        /// <summary>
        /// 释放
        /// </summary>
        /// <param name="ing"></param>
        protected virtual void Dispose(bool ing)
        {
            if (Disposed)
                return;        //不重复释放
            Disposed = true;   //让类型知道自己已经被释放

            //Point3d 有 DisposableWrapper,而DoubleCollection没有,
            //所以采取反射机制实现Collection.Dispose();
            var dispose = Collection.GetType().GetMethod("Dispose");
            dispose?.Invoke(Collection, null);
        }
        #endregion

    }
}

PublicEnumerator.cs 迭代元素

using System;
using System.Collections;

namespace JoinBox.BasalCurrency
{
    /// <summary>
    /// 迭代元素
    /// </summary>
    public class PublicEnumerator<T> : IEnumerator
    {
        public T[] _lnr;
        public PublicEnumerator(T[] arr)
        {
            _lnr = arr;
        }
        object IEnumerator.Current { get { return Current; } }

        //自举类型从这里返回当前元素T
        public T Current
        {
            get
            {
                try
                {
                    return _lnr[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
        int position = -1;      //计数
        public bool MoveNext()  //迭代
        {
            position++;
            return position < _lnr.Length;
        }
        public void Reset()   //初始计数赋值
        {
            position = -1;
        }
    }
}

(完)

posted @ 2021-02-21 22:00  惊惊  阅读(1387)  评论(0编辑  收藏  举报