明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 5360|回复: 11

[JIG] 带Jig效果的过一点绘制垂直于曲线的直线段

  [复制链接]
发表于 2011-1-4 22:55:29 | 显示全部楼层 |阅读模式
本帖最后由 qjchen 于 2011-12-20 11:53 编辑

这段代码主要是为了弥补LISP中grread较难实现捕捉的缺点
各位见笑了 :)

撰写此段代码的时候,学习了ahlzl兄和飞狐兄的相关代码,谢谢两位~

平台 : VS2008+CAD2007
命令 : JPE
效果 :如下



代码 :


  1. using System;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.GraphicsInterface;
  7. using Autodesk.AutoCAD.Runtime;
  8. namespace JigPerToCurve
  9. {
  10.     public class Class0 : IExtensionApplication
  11.     {
  12.         Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  13.         // 加载程序时的初始化操作
  14.         void IExtensionApplication.Initialize()
  15.         {
  16.             ed.WriteMessage("**Write by [url=mailto:qjchen@gmail.com]qjchen@gmail.com[/url], To draw a line per to a curve, Command:JPE");
  17.         }
  18.         // 卸载程序时的清除操作
  19.         void IExtensionApplication.Terminate()
  20.         {
  21.         }
  22.     }
  23.     public class Class1 : DrawJig
  24.     {
  25.         private Line ent;
  26.         private Curve curve;
  27.         [CommandMethod("jpe")]
  28.         public void Createjigjdx()
  29.         {
  30.             Database db = HostApplicationServices.WorkingDatabase;
  31.             Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  32.             PromptEntityOptions optEnt = new PromptEntityOptions("\n选择曲线:");
  33.             PromptEntityResult resEnt = ed.GetEntity(optEnt);
  34.             if (resEnt.Status == PromptStatus.OK)
  35.             {
  36.                 using (Transaction trans = db.TransactionManager.StartTransaction())
  37.                 {
  38.                     BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
  39.                     BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  40.                     curve = (Curve)(trans.GetObject(resEnt.ObjectId, OpenMode.ForWrite));
  41.                     ent = new Line(Point3d.Origin, Point3d.Origin);
  42.                     PromptResult resJig = ed.Drag(this);
  43.                     if (resJig.Status == PromptStatus.OK)
  44.                     {
  45.                         btr.AppendEntity(ent);
  46.                         trans.AddNewlyCreatedDBObject(ent, true);
  47.                     }
  48.                     trans.Commit();
  49.                 }
  50.             }
  51.         }
  52.         // Sampler函数用于检测用户的输入.
  53.         protected override SamplerStatus Sampler(JigPrompts prompts)
  54.         {
  55.             Database db = HostApplicationServices.WorkingDatabase;
  56.             JigPromptPointOptions optJigDis = new JigPromptPointOptions("\n请指定一个新的点");
  57.             optJigDis.UserInputControls = UserInputControls.Accept3dCoordinates;
  58.             PromptPointResult resJigDis = prompts.AcquirePoint(optJigDis);
  59.             //curPt就是现在屏幕上鼠标位置点
  60.             Point3d curPt = resJigDis.Value;
  61.             //下面这句话很重要,不然会出错,必须保证这个点是在线上
  62.             Point3d point = curve.GetClosestPointTo(curPt, false);
  63.             if (resJigDis.Status == PromptStatus.Cancel)
  64.             {
  65.                 return SamplerStatus.Cancel;
  66.             }
  67.             Vector3d vtan = curve.GetFirstDerivative(point);
  68.             Vector3d vnor0 = vtan.RotateBy(Math.PI / 2, Vector3d.ZAxis).GetNormal();
  69.             Vector3d vnor1 = vtan.RotateBy(-Math.PI / 2, Vector3d.ZAxis).GetNormal();
  70.             double vsize = (double)Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("VIEWSIZE");
  71.             Point3d point_per0 = point + vnor0.MultiplyBy(vsize / 5.0);
  72.             Point3d point_per1 = point + vnor1.MultiplyBy(vsize / 5.0);
  73.             //判断当前点在曲线的哪边,若相等的时候取默认的
  74.             if (point_per1.DistanceTo(curPt) < point_per0.DistanceTo(curPt))
  75.             {
  76.                 point_per0 = point_per1;
  77.             }
  78.             ent.StartPoint = point;
  79.             ent.EndPoint = point_per0;
  80.             return SamplerStatus.OK;
  81.         }
  82.         // WorldDraw函数用于刷新屏幕上显示的图形.
  83.         protected override bool WorldDraw(WorldDraw draw)
  84.         {
  85.             // 刷新画面.
  86.             draw.Geometry.Draw(ent);
  87.             return true;
  88.         }
  89.     }
  90. }


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 1明经币 +1 收起 理由
雪山飞狐_lzh + 1

查看全部评分

发表于 2011-1-4 23:17:38 | 显示全部楼层
点的计算也可以这样
var ver = (point - curpt).GetNormal() * vsize / 5.0;
ent.StartPoint = point;
ent.EndPoint = point + vec;
最近点与当前点的连线应该就是垂线吧
当然,如果相等还是应该按切向量的垂直方向
另外,还应该判断是否在曲线以外

 楼主| 发表于 2011-1-5 08:38:51 | 显示全部楼层
本帖最后由 qjchen 于 2011-1-5 08:40 编辑

To 飞狐兄~
谢谢指导,直接连接curPt和point确实是好方法:)
刚才我又仔细想了一下
最近点与当前点的连线应该就是垂线吧==> 这个不一定,在端部的地方就不是这样
当然,如果相等还是应该按切向量的垂直方向,另外,还应该判断是否在曲线以外==> 确实如此

我上面的程序,假如不考虑Jig的画,那么编起来倒是简单些,只需要GetPoint就可以了,这样子得到的点肯定在曲线上,但是后来我加上了Jig之后,就发现

  1. PromptPointResult resJigDis = prompts.AcquirePoint(optJigDis);
  2.           //curPt就是现在屏幕上鼠标位置点
  3.             Point3d curPt = resJigDis.Value;
  4.             //下面这句话很重要,不然会出错,必须保证这个点是在线上
  5.             Point3d point = curve.GetClosestPointTo(curPt, false);
复制代码

CurPt点只是鼠标当前位置点,并不保证在曲线上的,所以 .GetFirstDerivative会出错,而我的程序的目的是要完成 过曲线上一点做垂线的 ,而非过曲线外一点的(假如那样的画,用per捕捉即可),所以只好用了这个方法,所以就导致了后面 鼠标沿曲线走动的时候,若出了曲线区域,在端点的部分仍然采用垂线的做法。

这段程序的局限在于,其实Jig只是花哨用的,真正用捕捉取到曲线上点的时候,它无法正确画出用户需要的向曲线的哪边画垂线的目的。可能得修改一下,变成一个先确定取点,再Jig方向的程序(不过这个用Lisp可能更简单)。

谢谢飞狐兄的指导~




发表于 2011-3-30 23:28:29 | 显示全部楼层
好程序!请问复制代码后该保存什么格式呢?
发表于 2011-12-26 11:24:44 | 显示全部楼层
好程序啊。
发表于 2011-12-27 08:51:07 | 显示全部楼层
不错的程序,有实用意义。
发表于 2012-1-11 10:49:58 | 显示全部楼层
不错的程序,收藏,收后参考用!
发表于 2012-4-4 22:14:59 | 显示全部楼层
请问楼主:能不能不需要去掉选择曲线这一句:
PromptEntityOptions optEnt = new PromptEntityOptions("\n选择曲线:");
PromptEntityResult resEnt = ed.GetEntity(optEnt);

能直接通过jig移动时的点来获取此曲线吗?这样只需要1步操作。
简单说就是 如何获取通过某点的曲线呢?
不知道我表达清楚没有。
发表于 2012-4-10 11:49:06 | 显示全部楼层
正需要学习呢
发表于 2012-9-3 11:31:52 | 显示全部楼层
什么格式这个代码?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 16:43 , Processed in 0.175346 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表