cad.net 替换轻多段线和复杂实体的点+二度封装Collection类
轻多段线与复杂实体
Polyline
是轻多段线
Polyline2d
和Polyline3d
和PolyFaceMesh多面网格
等等这些是复杂实体,它们需要通过迭代器处理.
获取点集
先看一个通用的提取点集的做法,主要目的是针对轻多段线/二维多段线/三维多段线.
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不能自举类型而烦恼?那就来做这个操作吧!
我做了如下操作:
- 覆盖同名函数Point3dCollection,就是命名空间是自己的,而类型名是这个,这样你就不需要大改其他位置的代码了.
- 制作迭代器代替一次封装的迭代器,以自举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;
}
}
}
(完)