优化多段线的倒角
在QQ群为风吹桥动改写优化多段线的倒角程序,原代码使用DB库的曲线并用纯数学计算方式
///
/// 通过一个顶点将多义线倒圆角,本程序不支持多义线起点和终点处倒圆角
///
/// 多义线对象
/// 顶点索引号
/// 圆弧半径
public static void FilletatVertex(Polyline polyline, int vertexIndex, double radius)
{
Database db = HostApplicationServices.WorkingDatabase;//获取数据库
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;//获取editor对象
using (Transaction trans = db.TransactionManager.StartTransaction())//开始事务
{
try
{
//判断顶点索引号是否属于多义线;
if (vertexIndex = polyline.NumberOfVertices)
{
ed.WriteMessage("\n顶点无效。");
return;
}
else if ((polyline.GetBulgeAt(vertexIndex - 1) != 0) && (polyline.GetBulgeAt(vertexIndex) != 0))
{
ed.WriteMessage("\n顶点两侧不是直线。");
return;
}
else
{
Point2d pnt = polyline.GetPoint2dAt(vertexIndex);
Vector2d vec1 = polyline.GetPoint2dAt(vertexIndex - 1) - pnt;//由顶点与前一个顶点组成的向量
Vector2d vec2 = polyline.GetPoint2dAt(vertexIndex + 1) - pnt;//由顶点与后一个顶点组成的向量
double angle = vec1.GetAngleTo(vec2);//获得角点两侧线段间的角度变化
ed.WriteMessage(angle.ToString());
ed.WriteMessage("\n" + vec1.Length.ToString());
ed.WriteMessage("\n" + (radius / Math.Tan(angle / 2)).ToString());
ed.WriteMessage("\n" + vec2.Length.ToString());
ed.WriteMessage("\n" + (radius / Math.Tan(angle / 2)).ToString());
if ((vec1.Length
/// 为优化多段线倒角
///
/// 优化多段线
/// 顶点索引号
/// 倒角半径
/// 倒角类型
public static void ChamferAt(this Polyline polyline, int index, double radius, bool isFillet)
{
if (indexpolyline.NumberOfVertices - 2)
throw new System.Exception("错误的索引号");
if (polyline.GetSegmentType(index - 1) != SegmentType.Line || polyline.GetSegmentType(index) != SegmentType.Line)
throw new System.Exception("非直线段不能倒角");
//获取当前索引号的前后两段直线,并组合为Ge复合曲线
Curve3d[] c3ds =
new Curve3d[]
{
polyline.GetLineSegmentAt(index - 1),
polyline.GetLineSegmentAt(index)
};
var cc3d = new CompositeCurve3d(c3ds);
//试倒直角
//子曲线的个数有三种情况:
//1、=3时倒角方向正确
//2、=2时倒角方向相反
//3、=0或为直线时失败
c3ds =
cc3d.GetTrimmedOffset
(
radius,
Vector3d.ZAxis,
OffsetCurveExtensionType.Chamfer
);
if (c3ds.Length > 0 && c3ds is CompositeCurve3d)
{
var newcc3d = c3ds as CompositeCurve3d;
c3ds = newcc3d.GetCurves();
if (c3ds.Length == 3)
{
c3ds =
cc3d.GetTrimmedOffset
(
-radius,
Vector3d.ZAxis,
OffsetCurveExtensionType.Chamfer
);
if (c3ds.Length == 0 || c3ds is LineSegment3d)
{
throw new System.Exception("倒角半径过大");
}
}
else if (c3ds.Length == 2)
{
radius = -radius;
}
}
else
{
throw new System.Exception("倒角半径过大");
}
//GetTrimmedOffset会生成倒角+偏移,故先反方向倒角,再倒回
c3ds =
cc3d.GetTrimmedOffset
(
-radius,
Vector3d.ZAxis,
OffsetCurveExtensionType.Extend
);
OffsetCurveExtensionType type =
isFillet ?
OffsetCurveExtensionType.Fillet : OffsetCurveExtensionType.Chamfer;
c3ds =
c3ds.GetTrimmedOffset
(
radius,
Vector3d.ZAxis,
type
);
//将结果Ge曲线转为Db曲线,并将相关的数值反映到原曲线
Polyline plTemp = c3ds.ToCurve() as Polyline;
polyline.RemoveVertexAt(index);
polyline.AddVertexAt(index, plTemp.GetPoint2dAt(1), plTemp.GetBulgeAt(1), 0, 0);
polyline.AddVertexAt(index + 1, plTemp.GetPoint2dAt(2), 0, 0, 0);
}
public void test()
{
var db = HostApplicationServices.WorkingDatabase;
var doc = Application.DocumentManager.GetDocument(db);
var ed = doc.Editor;
var resEnt = ed.GetEntity("\n请选择优化多段线:");
var resInt = ed.GetInteger("\n请输入索引号:");
bool isFillet = false;
PromptDoubleOptions opt = new PromptDoubleOptions("\n请输入倒角半径:");
opt.Keywords.Add("F");
var resDbl = ed.GetDouble(opt);
if (resDbl.Status == PromptStatus.Keyword)
{
isFillet = true;
resDbl = ed.GetDouble(opt);
}
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Polyline pl = resEnt.ObjectId.GetObject(OpenMode.ForWrite) as Polyline;
ChamferAt(pl, resInt.Value, resDbl.Value, isFillet);
tr.Commit();
}
}
命令行的输入:
命令: ctest
请选择优化多段线:
请输入索引号: 3
请输入倒角半径 : f
请输入倒角半径 : 5
命令: ctest
请选择优化多段线:
请输入索引号: 2
请输入倒角半径 : 5
倒角效果:
顶飞狐版主呀,学习了!
楼主强大,顶 修正试倒角时的Bug,2楼代码已更改
太好的东西,正是需要的资料。 要是有LISP代码就好了。 路过并表示强烈支持!
页:
[1]