1 Curve Measurement Functions介绍
在AutoLisp开发里面,有一组以vlax-curve-get开头的曲线测量函数比较好用,主要功能是提供曲线上某一点的坐标、距离、切线。这些函数经常会被用到,如果要自己实现需要非常好的数学功底,还好我们只需要理解并拿来用即可。
Curve Measurement函数的共同之处是都是与曲线上的某一点有关,使用时需要用到曲线参数param才能得到这一点的坐标、距离、切线,且不同的曲线其param含义大不相同。下面我就param在各种曲线中的含义收集整理如下:
1)在line中,param为点在直线上距离起点长度,直线起点param为0,终点param为直线的长度。
2)在arc、circle、ellipse中,param为圆心到曲线起点逆时针旋转到该点的弧度值;circle、ellipse起点param为0,终点param为2pi,arc起点param对应圆弧dxf的50码值,终点param对应圆弧dxf的51码值。
3)在polyline中,param为计算点在polyline顶点上的顺序位置值,该值整数为计算点在polyline上的顶点顺序,以0为计数起点,小数部分为计算点在该polyline片段上的长度比率。
4)在Spline中,param是以Spline的拟合点进行直线连线,param表示在该直线上距起点的距离。起点param为0,终点param为直线连线的总长度。
5)vlax-curve-getFirstDeriv 函数返回曲线在某点的切向量,但是我们经常要用的是法向量,将其旋转pi/2即可。
掌握了各曲线param的含义,就可以进行与曲线点位相关的各种操作了,因此我也将Curve Measurement Function译为询点函数。在.net开发中这些函数封装在Curve类中,以虚函数的形式提供。
根据类的继承关系可知,Curve类是各种曲线类的父类,继承Curve的子类自然拥有这些方法,因为是虚函数,所有最终还是在各子类中实现。
2 Curve Measurement Functions实例
下面展示的实例是在polyline对象上根据距离表达式画出相应位置的径向线,在绘制桥位平面图时经常用到,分五步操作后即可绘制出所需要的径向线。
1)选择一多段线,一般指路线设计线。
2)选择起点,即第一个径向线的位置。
3)输入跨径表达式,如‘’3+3*30+4*30+3”。
4)输入单幅宽度,如为正表示左右幅均绘制,如为负表示只绘制左幅或者右幅。
5)选择一点作为前进方向,同时当上一步输入单幅宽度为负时该点也指定了是绘制在左幅还是右幅。
3 主要代码
主要代码如下:
[CommandMethod("bat_gg")]
public void Sub21()
{ObjectId id = new ObjectId();Point3d pt1 = new Point3d();Point3d pt2 = new Point3d();string stakeExpress = "3+3*30+4*30+3";double roadWidth = 12.75;if (InputHelper.GetEntityId(ref id, "\n选择一多段线", TypeValueHelper.Polyline) &&InputHelper.GetPoint(ref pt1, "\n选择起点") &&InputHelper.GetString(ref stakeExpress, "\n输入跨径表达式") &&InputHelper.GetDouble(ref roadWidth, "\n输入单幅宽度(正为双侧,负为单侧)") &&InputHelper.GetPoint(ref pt2, "\n选择一点作为方向")){Polyline pl = EntityHelper.GetEntityById(id) as Polyline;double length1 = pl.GetDistanceAtParameter(pl.GetParameterAtPoint(pl.GetClosestPointTo(pt1, false)));double length2 = pl.GetDistanceAtParameter(pl.GetParameterAtPoint(pl.GetClosestPointTo(pt2, false)));//绘图左右侧判断Vector3d v1 = pt2 - pt1;Vector3d v2 = pl.GetClosestPointTo(pt2, true) - pt1;double rotateAngle = v1.CrossProduct(v2).DotProduct(Vector3d.ZAxis) > 0 ? -Math.PI / 2 : Math.PI / 2;//与桩号的方向有关if (length2 < length1) rotateAngle = -rotateAngle;//所绘制图元List<Entity> list = new List<Entity>();List<double> expresslist = StringHelper.ParseDoubleList(stakeExpress);expresslist.Insert(0, 0);double x = length1;foreach (var item in expresslist){//求下一个跨径线的位置x = x + item * ((length1 < length2) ? 1 : -1);//实际距离不能超越多段线本身if (x >= 0 && x <= pl.Length){Point3d pt = pl.GetPointAtDist(x);Vector3d v = pl.GetFirstDerivative(pt).RotateBy(rotateAngle, Vector3d.ZAxis);if (roadWidth < 0) list.Add(new Line(pt, pt - v / v.Length * roadWidth).SetLayer("中心线"));if (roadWidth > 0) list.Add(new Line(pt - v / v.Length * roadWidth, pt + v / v.Length * roadWidth).SetLayer("中心线"));}else break;}EntityHelper.Post2CurrentSpace(list);}
}