[飞马小程序] 带Jig效果的过一点绘制垂直于曲线的直线段
本帖最后由 qjchen 于 2011-12-20 11:53 编辑这段代码主要是为了弥补LISP中grread较难实现捕捉的缺点
各位见笑了 :)
撰写此段代码的时候,学习了ahlzl兄和飞狐兄的相关代码,谢谢两位~
平台 : VS2008+CAD2007
命令 : JPE
效果 :如下
代码 :
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
namespace JigPerToCurve
{
public class Class0 : IExtensionApplication
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
// 加载程序时的初始化操作
void IExtensionApplication.Initialize()
{
ed.WriteMessage("**Write by qjchen@gmail.com, To draw a line per to a curve, Command:JPE");
}
// 卸载程序时的清除操作
void IExtensionApplication.Terminate()
{
}
}
public class Class1 : DrawJig
{
private Line ent;
private Curve curve;
public void Createjigjdx()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
PromptEntityOptions optEnt = new PromptEntityOptions("\n选择曲线:");
PromptEntityResult resEnt = ed.GetEntity(optEnt);
if (resEnt.Status == PromptStatus.OK)
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt, OpenMode.ForWrite);
curve = (Curve)(trans.GetObject(resEnt.ObjectId, OpenMode.ForWrite));
ent = new Line(Point3d.Origin, Point3d.Origin);
PromptResult resJig = ed.Drag(this);
if (resJig.Status == PromptStatus.OK)
{
btr.AppendEntity(ent);
trans.AddNewlyCreatedDBObject(ent, true);
}
trans.Commit();
}
}
}
// Sampler函数用于检测用户的输入.
protected override SamplerStatus Sampler(JigPrompts prompts)
{
Database db = HostApplicationServices.WorkingDatabase;
JigPromptPointOptions optJigDis = new JigPromptPointOptions("\n请指定一个新的点");
optJigDis.UserInputControls = UserInputControls.Accept3dCoordinates;
PromptPointResult resJigDis = prompts.AcquirePoint(optJigDis);
//curPt就是现在屏幕上鼠标位置点
Point3d curPt = resJigDis.Value;
//下面这句话很重要,不然会出错,必须保证这个点是在线上
Point3d point = curve.GetClosestPointTo(curPt, false);
if (resJigDis.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
Vector3d vtan = curve.GetFirstDerivative(point);
Vector3d vnor0 = vtan.RotateBy(Math.PI / 2, Vector3d.ZAxis).GetNormal();
Vector3d vnor1 = vtan.RotateBy(-Math.PI / 2, Vector3d.ZAxis).GetNormal();
double vsize = (double)Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("VIEWSIZE");
Point3d point_per0 = point + vnor0.MultiplyBy(vsize / 5.0);
Point3d point_per1 = point + vnor1.MultiplyBy(vsize / 5.0);
//判断当前点在曲线的哪边,若相等的时候取默认的
if (point_per1.DistanceTo(curPt) < point_per0.DistanceTo(curPt))
{
point_per0 = point_per1;
}
ent.StartPoint = point;
ent.EndPoint = point_per0;
return SamplerStatus.OK;
}
// WorldDraw函数用于刷新屏幕上显示的图形.
protected override bool WorldDraw(WorldDraw draw)
{
// 刷新画面.
draw.Geometry.Draw(ent);
return true;
}
}
}
点的计算也可以这样
var ver = (point - curpt).GetNormal() * vsize / 5.0;
ent.StartPoint = point;
ent.EndPoint = point + vec;
最近点与当前点的连线应该就是垂线吧
当然,如果相等还是应该按切向量的垂直方向
另外,还应该判断是否在曲线以外
本帖最后由 qjchen 于 2011-1-5 08:40 编辑
To 飞狐兄~
谢谢指导,直接连接curPt和point确实是好方法:)
刚才我又仔细想了一下
最近点与当前点的连线应该就是垂线吧==> 这个不一定,在端部的地方就不是这样
当然,如果相等还是应该按切向量的垂直方向,另外,还应该判断是否在曲线以外==> 确实如此
我上面的程序,假如不考虑Jig的画,那么编起来倒是简单些,只需要GetPoint就可以了,这样子得到的点肯定在曲线上,但是后来我加上了Jig之后,就发现
PromptPointResult resJigDis = prompts.AcquirePoint(optJigDis);
//curPt就是现在屏幕上鼠标位置点
Point3d curPt = resJigDis.Value;
//下面这句话很重要,不然会出错,必须保证这个点是在线上
Point3d point = curve.GetClosestPointTo(curPt, false);
CurPt点只是鼠标当前位置点,并不保证在曲线上的,所以 .GetFirstDerivative会出错,而我的程序的目的是要完成 过曲线上一点做垂线的 ,而非过曲线外一点的(假如那样的画,用per捕捉即可),所以只好用了这个方法,所以就导致了后面 鼠标沿曲线走动的时候,若出了曲线区域,在端点的部分仍然采用垂线的做法。
这段程序的局限在于,其实Jig只是花哨用的,真正用捕捉取到曲线上点的时候,它无法正确画出用户需要的向曲线的哪边画垂线的目的。可能得修改一下,变成一个先确定取点,再Jig方向的程序(不过这个用Lisp可能更简单)。
谢谢飞狐兄的指导~
好程序!请问复制代码后该保存什么格式呢? 好程序啊。
不错的程序,有实用意义。 不错的程序,收藏,收后参考用! 请问楼主:能不能不需要去掉选择曲线这一句:
PromptEntityOptions optEnt = new PromptEntityOptions("\n选择曲线:");
PromptEntityResult resEnt = ed.GetEntity(optEnt);
能直接通过jig移动时的点来获取此曲线吗?这样只需要1步操作。
简单说就是 如何获取通过某点的曲线呢?
不知道我表达清楚没有。
正需要学习呢 什么格式这个代码?
页:
[1]
2