filterList = new TypedValue[]
{
new TypedValue((int)DxfCode.Start, "LINE,CIRCLE,ELLIPSE,ARC,SPLINE,POLYLINE")
};
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using IfoxDemo;
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
namespace AutoCADArcEncryption
{
public static class 加密凸度多段线
{
[CommandMethod("xx1")]
public static void 弧转多段线()
{
using var tr = new DBTrans();
// 创建一个弧
// 定义选择过滤器,只允许选择椭圆和样条曲线
TypedValue[] filterList = new TypedValue[]
{
new TypedValue((int)DxfCode.Start, "ELLIPSE,SPLINE")
};
SelectionFilter filter = new SelectionFilter(filterList);
// 提示用户选择实体
PromptSelectionOptions pso = new PromptSelectionOptions();
pso.MessageForAdding = "\n选择椭圆或样条曲线: ";
PromptSelectionResult psr = Env.Editor.GetSelection(pso, filter);
SelectionSet ss = psr.Value;
if (psr.Status != PromptStatus.OK) return;
foreach (SelectedObject so in ss)
{
if (so != null)
{
Curve curve = (Curve)tr.GetObject(so.ObjectId, OpenMode.ForRead).Clone();
Polyline polyline = null;
if (curve is Ellipse ellipse)
{
Spline sp = ellipse.Spline;
polyline = (Polyline)sp.ToPolyline();
}
else if (curve is Spline spline)
{
// 将样条曲线直接转换为多段线
polyline = (Polyline)spline.ToPolyline();
}
if (polyline == null)
{
return;
}
Env.Database.AddEntityToModeSpace(polyline);
}
}
Env.Editor.ZoomExtents();
}
///
/// 处理多段线,将带有凸度的弧段加密为直线段
///
/// 原始多段线
/// 处理后的多段线
public static Polyline 多段线去凸度(this Polyline original, int num)
{
Polyline cur = new Polyline();
// 检查多段线是否有凸度
bool hasBulge = false;
for (int i = 0; i < original.NumberOfVertices; i++)
{
if (original.GetBulgeAt(i) != 0.0)
{
hasBulge = true;
break;
}
}
if (!hasBulge) return cur; // 无凸度,直接返回空值
// 创建新多段线并复制属性
//Polyline newPolyline = new Polyline();
//newPolyline.Closed = original.Closed;
//newPolyline.Layer = original.Layer;
//newPolyline.Color = original.Color;
//newPolyline.Linetype = original.Linetype;
Polyline newPolyline = new Polyline();
DBObjectCollection dbo = new DBObjectCollection();
var original_clone = original.Clone() as Polyline;
original_clone.Explode(dbo);
List curs = new List();
foreach (var item in dbo)
{
if (item is Polyline)
{
curs.Add(item as Polyline);
}
if (item is Line line)
{
Polyline polyline = new Polyline();
polyline.AddVertexAt(0, line.StartPoint.toPoint2d(), 0, 0, 0);
polyline.AddVertexAt(1, line.EndPoint.toPoint2d(), 0, 0, 0);
curs.Add(polyline);
}
if (item is Arc arc)
{
var pl2 = 加密弧转多段线(arc, num);
curs.Add(pl2 as Polyline);
}
}
var results = 首尾相连.Makepl(curs);
var result = results[0];
if (result is Polyline pl) { pl.Closed = true; }
return result;
}
public static Polyline 加密弧转多段线(Arc arc, int pointCount)
{
// 创建一个新的多段线对象,用于存储加密后的结果
Polyline polyline = new Polyline();
// 获取圆弧的起始角度
double startAngle = arc.StartAngle;
// 获取圆弧的结束角度
double endAngle = arc.EndAngle;
// 获取圆弧的圆心点
Point3d center = arc.Center;
// 获取圆弧的半径
double radius = arc.Radius;
// 计算圆弧的角度差,考虑到可能存在的逆时针情况
double delta = endAngle - startAngle;
if (delta < 0)
{
// 若角度差为负,说明是逆时针圆弧,将其转换为正的角度差
delta += 2 * Math.PI;
}
// 计算每个细分点之间的角度步长
double angleStep = delta / (pointCount - 1);
// 添加圆弧的起始点作为多段线的第一个顶点
polyline.AddVertexAt(0, new Point2d(arc.StartPoint.X, arc.StartPoint.Y), 0, 0, 0);
// 循环生成除起始点和结束点之外的加密点
for (int i = 1; i < pointCount - 1; i++)
{
// 计算当前加密点对应的角度
double currentAngle = startAngle + i * angleStep;
// 对角度进行规范化处理,确保其在 [0, 2π) 范围内
currentAngle %= 2 * Math.PI;
if (currentAngle < 0)
{
currentAngle += 2 * Math.PI;
}
// 根据当前角度和圆心、半径计算加密点的 X 坐标
double x = center.X + radius * Math.Cos(currentAngle);
// 根据当前角度和圆心、半径计算加密点的 Y 坐标
double y = center.Y + radius * Math.Sin(currentAngle);
// 将计算得到的加密点添加到多段线中
polyline.AddVertexAt(i, new Point2d(x, y), 0, 0, 0);
}
// 添加圆弧的结束点作为多段线的最后一个顶点
polyline.AddVertexAt(pointCount - 1, new Point2d(arc.EndPoint.X, arc.EndPoint.Y), 0, 0, 0);
// 返回加密后的多段线对象
return polyline;
}
public static Polyline 加密圆转多段线(Circle circle, int pointCount)
{
Polyline polyline = new Polyline();
Point3d center = circle.Center;
double radius = circle.Radius;
double angleStep = 2 * Math.PI / pointCount;
for (int i = 0; i < pointCount; i++)
{
double currentAngle = i * angleStep;
double x = center.X + radius * Math.Cos(currentAngle);
double y = center.Y + radius * Math.Sin(currentAngle);
polyline.AddVertexAt(i, new Point2d(x, y), 0, 0, 0);
}
// 闭合多段线
polyline.Closed = true;
return polyline;
}
///
/// 判断多段线是否有凸度
///
/// 要检查的多段线对象
/// 如果多段线有凸度返回 true,否则返回 false
public static bool 有凸度(this Polyline polyline)
{
for (int i = 0; i < polyline.NumberOfVertices; i++)
{
if (polyline.GetBulgeAt(i) != 0.0)
{
return true;
}
}
return false;
}
}
public static class 首尾相连
{
public static List Make(List curs, double rongcha = 0.0001)
{
List lianxianfanhui = new List();
List> cursref = new List>();
首尾相连分组迭代(curs, ref cursref, rongcha);
foreach (List curl in cursref)
{
Curve pl = 连续的线连成多段线(curl, rongcha);
lianxianfanhui.Add(pl);
}
return lianxianfanhui;
}
public static List Makepl(List curs, double rongcha = 0.0001)
{
List lianxianfanhui = new List();
List> cursref = new List>();
首尾相连分组迭代pl(curs, ref cursref, rongcha);
foreach (List curl in cursref)
{
Polyline pl = 连续的线连成多段线pl(curl, rongcha);
lianxianfanhui.Add(pl);
}
return lianxianfanhui;
}
static void 首尾相连分组迭代(List curs, ref List> fenzu, double rongcha)
{
List yizu = new List();
yizu.Add(curs[0]);
curs.Remove(curs[0]);
向后找线(ref yizu, ref curs, rongcha);
向前找线(ref yizu, ref curs, rongcha);
fenzu.Add(yizu);
if (curs.Count > 0) 首尾相连分组迭代(curs, ref fenzu, rongcha);
}
static void 首尾相连分组迭代pl(List curs, ref List> fenzu, double rongcha)
{
List yizu = new List();
yizu.Add(curs[0]);
curs.Remove(curs[0]);
向后找线pl(ref yizu, ref curs, rongcha);
向前找线pl(ref yizu, ref curs, rongcha);
fenzu.Add(yizu);
if (curs.Count > 0) 首尾相连分组迭代pl(curs, ref fenzu, rongcha);
}
static void 向后找线pl(ref List yizu, ref List curs, double rongcha)
{
var curlast = yizu[yizu.Count - 1];
var curfirst = yizu[0];
Point3d pStart = curfirst.StartPoint;
Point3d pEnd = curlast.EndPoint;
Vector3d vtstart = curfirst.GetFirstDerivative(pStart);
Vector3d vtend = curlast.GetFirstDerivative(pEnd).Negate();
List nend = new List();
for (int i = 0; i < curs.Count; i++)
{
Polyline cur = curs[i];
if (pEnd.IsEqualTo(cur.StartPoint, new Tolerance(rongcha, rongcha)))
{
nend.Add(i);
}
else if (pEnd.IsEqualTo(cur.EndPoint, new Tolerance(rongcha, rongcha)))
{
curs[i] = Reversepl(cur);
nend.Add(i);
}
}
if (nend.Count > 0)
{
var curscopy = curs;
var ii = (from i in nend orderby nsz逆时针夹角(curscopy[i].GetFirstDerivative(curscopy[i].StartPoint), vtend) select i).First();
yizu.Add(curs[ii]);
curs.RemoveAt(ii);
if (curs.Count > 0) 向后找线pl(ref yizu, ref curs, rongcha);
}
}
static void 向前找线pl(ref List yizu, ref List curs, double rongcha)
{
var curlast = yizu[yizu.Count - 1];
var curfirst = yizu[0];
Point3d pStart = curfirst.StartPoint;
Point3d pEnd = curlast.EndPoint;
Vector3d vtstart = curfirst.GetFirstDerivative(pStart);
Vector3d vtend = curlast.GetFirstDerivative(pEnd).Negate();
List nfirst = new List();
for (int i = 0; i < curs.Count; i++)
{
Polyline cur = curs[i];
if (pStart.IsEqualTo(cur.StartPoint, new Tolerance(rongcha, rongcha)))
{
curs[i] = Reversepl(cur);
nfirst.Add(i);
}
else if (pStart.IsEqualTo(cur.EndPoint, new Tolerance(rongcha, rongcha)))
{
nfirst.Add(i);
}
}
if (nfirst.Count > 0)
{
var curscopy = curs;
var ii = (from i in nfirst orderby nsz逆时针夹角(curscopy[i].GetFirstDerivative(curscopy[i].EndPoint).Negate(), vtstart) select i).First();
yizu.Insert(0, curs[ii]);
curs.RemoveAt(ii);
if (curs.Count > 0) 向前找线pl(ref yizu, ref curs, rongcha);
else return;
}
}
static void 向后找线(ref List yizu, ref List curs, double rongcha)
{
var curlast = yizu[yizu.Count - 1];
var curfirst = yizu[0];
Point3d pStart = curfirst.StartPoint;
Point3d pEnd = curlast.EndPoint;
Vector3d vtstart = curfirst.GetFirstDerivative(pStart);
Vector3d vtend = curlast.GetFirstDerivative(pEnd).Negate();
List nend = new List();
for (int i = 0; i < curs.Count; i++)
{
Curve cur = curs[i];
if (pEnd.IsEqualTo(cur.StartPoint, new Tolerance(rongcha, rongcha)))
{
nend.Add(i);
}
else if (pEnd.IsEqualTo(cur.EndPoint, new Tolerance(rongcha, rongcha)))
{
curs[i] = ReverseCur(cur);
nend.Add(i);
}
}
if (nend.Count > 0)
{
var curscopy = curs;
var ii = (from i in nend orderby nsz逆时针夹角(curscopy[i].GetFirstDerivative(curscopy[i].StartPoint), vtend) select i).First();
yizu.Add(curs[ii]);
curs.RemoveAt(ii);
if (curs.Count > 0) 向后找线(ref yizu, ref curs, rongcha);
}
}
static void 向前找线(ref List yizu, ref List curs, double rongcha)
{
var curlast = yizu[yizu.Count - 1];
var curfirst = yizu[0];
Point3d pStart = curfirst.StartPoint;
Point3d pEnd = curlast.EndPoint;
Vector3d vtstart = curfirst.GetFirstDerivative(pStart);
Vector3d vtend = curlast.GetFirstDerivative(pEnd).Negate();
List nfirst = new List();
for (int i = 0; i < curs.Count; i++)
{
Curve cur = curs[i];
if (pStart.IsEqualTo(cur.StartPoint, new Tolerance(rongcha, rongcha)))
{
curs[i] = ReverseCur(cur);
nfirst.Add(i);
}
else if (pStart.IsEqualTo(cur.EndPoint, new Tolerance(rongcha, rongcha)))
{
nfirst.Add(i);
}
}
if (nfirst.Count > 0)
{
var curscopy = curs;
var ii = (from i in nfirst orderby nsz逆时针夹角(curscopy[i].GetFirstDerivative(curscopy[i].EndPoint).Negate(), vtstart) select i).First();
yizu.Insert(0, curs[ii]);
curs.RemoveAt(ii);
if (curs.Count > 0) 向前找线(ref yizu, ref curs, rongcha);
else return;
}
}
static double nsz逆时针夹角(Vector3d v1, Vector3d v2)
{
double rt = v2.RotateBy(Math.PI * 2 - v1.AngleOnPlane(new Plane()), Vector3d.ZAxis).AngleOnPlane(new Plane());
if (Math.Abs(rt - Math.PI * 2) < 0.001) rt = 0;
return rt;
}
public static Polyline 连续的线连成多段线(List curlist, double rongcha)
{
Polyline pl = new Polyline();
if (curlist.Count == 0) return null;
if (curlist.Count == 1) return curlist[0].CurvetoPolyline1();
//判断线的正反
if (curlist[0].StartPoint.IsEqualTo(curlist[1].StartPoint, new Tolerance(rongcha, rongcha)) || curlist[0].StartPoint.IsEqualTo(curlist[1].EndPoint, new Tolerance(rongcha, rongcha)))
{ curlist[0] = ReverseCur(curlist[0]); }
for (int i = 1; i < curlist.Count; i++)
{
if (curlist[i].EndPoint.IsEqualTo(curlist[i - 1].StartPoint, new Tolerance(rongcha, rongcha)) || curlist[i].EndPoint.IsEqualTo(curlist[i - 1].EndPoint, new Tolerance(rongcha, rongcha)))
curlist[i] = ReverseCur(curlist[i]);
}
int k = 0;
for (int i = 0; i < curlist.Count; i++)
{
Curve cur = curlist[i];
if (cur is Line)
{
Point2d ptve = (cur.StartPoint.toPoint2d1());
pl.AddVertexAt(k++, ptve, 0, 0, 0);
}
else if (cur is Arc arc)
{
Point2d ptve = (cur.StartPoint.toPoint2d1());
double tudu = ArcBulge(arc, arc.StartPoint, arc.EndPoint);
pl.AddVertexAt(k++, ptve, tudu, 0, 0);
}
else if (cur is Polyline pl0)
{
if (pl0.Normal.Z == -1) pl0.TransformBy(Matrix3d.Mirroring(new Plane()));
for (int ii = 0; ii < pl0.NumberOfVertices - 1; ii++)
{
pl.AddVertexAt(k++, pl0.GetPoint2dAt(ii), pl0.GetBulgeAt(ii), 0, 0);
}
}
else if (cur is Spline spl)
{
Polyline p = spl.CurvetoPolyline1() as Polyline;
for (int ii = 0; ii < p.NumberOfVertices - 1; ii++)
{
pl.AddVertexAt(k++, p.GetPoint2dAt(ii), p.GetBulgeAt(ii), 0, 0); ;
}
}
else
{
Spline s = cur.Spline;
Polyline p = s.CurvetoPolyline1();
for (int ii = 0; ii < p.NumberOfVertices - 1; ii++)
{
pl.AddVertexAt(k++, p.GetPoint2dAt(ii), p.GetBulgeAt(ii), 0, 0); ;
}
}
}
Point2d ptend = (curlist[curlist.Count - 1].EndPoint.toPoint2d1());
pl.AddVertexAt(k, ptend, 0, 0, 0);
return pl;
}
public static Polyline 连续的线连成多段线pl(List curlist, double rongcha)
{
Polyline pl = new Polyline();
if (curlist.Count == 0) return null;
if (curlist.Count == 1) return curlist[0].CurvetoPolyline1();
//判断线的正反
if (curlist[0].StartPoint.IsEqualTo(curlist[1].StartPoint, new Tolerance(rongcha, rongcha)) || curlist[0].StartPoint.IsEqualTo(curlist[1].EndPoint, new Tolerance(rongcha, rongcha)))
{ curlist[0] = Reversepl(curlist[0]); }
for (int i = 1; i < curlist.Count; i++)
{
if (curlist[i].EndPoint.IsEqualTo(curlist[i - 1].StartPoint, new Tolerance(rongcha, rongcha)) || curlist[i].EndPoint.IsEqualTo(curlist[i - 1].EndPoint, new Tolerance(rongcha, rongcha)))
curlist[i] = Reversepl(curlist[i]);
}
int k = 0;
for (int i = 0; i < curlist.Count; i++)
{
Curve cur = curlist[i];
if (cur is Line)
{
Point2d ptve = (cur.StartPoint.toPoint2d1());
pl.AddVertexAt(k++, ptve, 0, 0, 0);
}
else if (cur is Arc arc)
{
Point2d ptve = (cur.StartPoint.toPoint2d1());
double tudu = ArcBulge(arc, arc.StartPoint, arc.EndPoint);
pl.AddVertexAt(k++, ptve, tudu, 0, 0);
}
else if (cur is Polyline pl0)
{
if (pl0.Normal.Z == -1) pl0.TransformBy(Matrix3d.Mirroring(new Plane()));
for (int ii = 0; ii < pl0.NumberOfVertices - 1; ii++)
{
pl.AddVertexAt(k++, pl0.GetPoint2dAt(ii), pl0.GetBulgeAt(ii), 0, 0);
}
}
else if (cur is Spline spl)
{
Polyline p = spl.CurvetoPolyline1() as Polyline;
for (int ii = 0; ii < p.NumberOfVertices - 1; ii++)
{
pl.AddVertexAt(k++, p.GetPoint2dAt(ii), p.GetBulgeAt(ii), 0, 0); ;
}
}
else
{
Spline s = cur.Spline;
Polyline p = s.CurvetoPolyline1();
for (int ii = 0; ii < p.NumberOfVertices - 1; ii++)
{
pl.AddVertexAt(k++, p.GetPoint2dAt(ii), p.GetBulgeAt(ii), 0, 0); ;
}
}
}
Point2d ptend = (curlist[curlist.Count - 1].EndPoint.toPoint2d1());
pl.AddVertexAt(k, ptend, 0, 0, 0);
return pl;
}
public static Polyline CurvetoPolyline1(this Curve cur)
{
Polyline plrt = new Polyline();
if (cur is Polyline pl)
{
plrt = pl;
}
if (cur is Line ll)
{
plrt.AddVertexAt(0, (ll.StartPoint.toPoint2d1()), 0, 0, 0);
plrt.AddVertexAt(1, (ll.EndPoint.toPoint2d1()), 0, 0, 0);
}
if (cur is Arc arc)
{
plrt.AddVertexAt(0, (arc.StartPoint.toPoint2d1()), ArcBulge(arc, arc.StartPoint, arc.EndPoint), 0, 0);
plrt.AddVertexAt(1, (arc.EndPoint.toPoint2d1()), 0, 0, 0);
}
if (cur is Circle cir)
{
plrt.AddVertexAt(0, (cir.StartPoint.toPoint2d1()), Math.Tan(Math.PI / 4), 0, 0);
plrt.AddVertexAt(1, (cir.GetPointAtDist(cir.Circumference / 2).toPoint2d1()), Math.Tan(Math.PI / 4), 0, 0);
plrt.AddVertexAt(2, (cir.StartPoint.toPoint2d1()), 0, 0, 0);
}
if (cur is Spline spl)
{
for (int i = 0; i <= 100; i++)
{
double dist = (spl.GetDistAtPoint(spl.EndPoint) - spl.GetDistAtPoint(spl.StartPoint)) / 100;
plrt.AddVertexAt(i, (spl.GetPointAtDist(dist * i).Convert2d(new Plane())), 0, 0, 0);
}
//plrt = spl.SplineToPolyline(1e-3);
//plrt = spl.ToPolyline() as Polyline;
}
if (cur is Ellipse ell)
{
for (int i = 0; i <= 100; i++)
{
double dist = (ell.GetDistAtPoint(ell.EndPoint) - ell.GetDistAtPoint(ell.StartPoint)) / 100;
plrt.AddVertexAt(i, (ell.GetPointAtDist(dist * i).Convert2d(new Plane())), 0, 0, 0);
}
//plrt = ell.Spline.SplineToPolyline(1e-3);
//plrt = ell.Spline.ToPolyline() as Polyline;
}
return plrt;
}
static double ArcBulge(this Arc arc, Point3d pfist, Point3d pend)
{
Point3d midpt = arc.GetPointAtDist(arc.GetDistanceAtParameter(arc.EndParam) / 2);
Vector3d vtse = pend - pfist;
Vector3d vtsm = midpt - pfist;
bool arcni = vtsm.CrossProduct(vtse).Z > 0 ? true : false;
double bulge = Math.Tan(arc.TotalAngle / 4);//凸度是圆心角的四分之一的正切
bulge *= arcni ? 1 : -1;
return bulge;
}
static Curve ReverseCur(this Curve cur)
{
if (cur.Closed == true) return cur;
else if (cur is Line l)
{
return new Line(l.EndPoint, l.StartPoint);
}
else if (cur is Arc arc)
{
Polyline pl = new Polyline();
Point3d st = arc.EndPoint;
Point3d en = arc.StartPoint;
double tudu = ArcBulge(arc, arc.EndPoint, arc.StartPoint);
pl.AddVertexAt(0, st.toPoint2d1(), tudu, 0, 0);
pl.AddVertexAt(1, en.toPoint2d1(), 0, 0, 0);
return pl;
}
else if (cur is Polyline pl)
{
Polyline plnew = new Polyline();
int n = pl.NumberOfVertices;
List tudu = new List();
List jiedian = new List();
for (int i = 0; i < n; i++)
{
tudu.Add(pl.GetBulgeAt(i));
jiedian.Add(pl.GetPoint2dAt(i));
}
jiedian.Reverse();
tudu.Reverse();
tudu.RemoveAt(0);
tudu.Add(0);
for (int i = 0; i < n; i++)
{
plnew.AddVertexAt(i, jiedian[i], -tudu[i], 0, 0);
}
return plnew;
}
else
{
Spline s = cur.Spline;
List pts = new List();
double leng = s.GetDistanceAtParameter(s.EndParam);
pts.Add(s.StartPoint);
for (int i = 1; i < 100; i++)
{
pts.Add(s.GetPointAtDist(leng / 100 * i));
}
pts.Add(s.EndPoint);
pts.Reverse();
Polyline plnew = new Polyline();
for (int i = 0; i <= 100; i++)
{
plnew.AddVertexAt(i, pts[i].toPoint2d1(), 0, 0, 0);
}
return plnew;
}
}
static Polyline Reversepl(this Polyline pl)
{
if (pl.Closed == true) return pl;
Polyline plnew = new Polyline();
int n = pl.NumberOfVertices;
List tudu = new List();
List jiedian = new List();
for (int i = 0; i < n; i++)
{
tudu.Add(pl.GetBulgeAt(i));
jiedian.Add(pl.GetPoint2dAt(i));
}
jiedian.Reverse();
tudu.Reverse();
tudu.RemoveAt(0);
tudu.Add(0);
for (int i = 0; i < n; i++)
{
plnew.AddVertexAt(i, jiedian[i], -tudu[i], 0, 0);
}
return plnew;
}
static Point2d toPoint2d1(this Point3d pt)
{
var pt2d = new Point2d(pt.X, pt.Y);
return pt2d;
}
}
}