000

Index Labels

Dragging a Line in Certain Angle

.
This article is inspired by a question posted in the Autodesk's Visual Basic Customization user forum. Baiscally, while drawing a line, after picking the start point, the user wants the ghost line only stretch in certain direction/angle, similar effect as the Ortho-On mode. Well, as a programmer, not a drafter/designer, I am not very sure how often this kind of fuctionality is desired in AutoCAD use. If one wants to draw a line that he knows the line's start/end point, or start point, lenght and direction/angle, he can alway enter them easily at command line. However I can imagine that during designing (nt drafting) process, the designer may want to draw a line, starting at a known point and she'd like it to be stretched at certain angle with undecided length.

Regardless it possible use/benefit an AutoCAD user may find, here is the code to do this. Yes, as you may have guessed, I used TransientGraphics again.

Here is the class that do the dynamic dragging. At the end of AngledDrag() call, the class provides two points (Point3d) - StartPoint and EndPoint as public read-only properties for the calling procedure to use.

using System;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

namespace AngleLockedDrag
{
public class AngledDrag
{
private Document _dwg;
private Database _db;
private Editor _editor;

private Point3d _startPoint = new Point3d(0.0, 0.0, 0.0);
private Point3d _endPoint = new Point3d(0.0, 0.0, 0.0);

private double _dragAngle = 45.0;

private Line _dragLine = null;
private int _colorIndex = 1;

public AngledDrag(Document dwg)
{
_dwg = dwg;
_db = dwg.Database;
_editor = dwg.Editor;
}

public Point3d StartPoint
{
get { return _startPoint; }
}

public Point3d EndPoint
{
get { return _endPoint; }
}

#region public methods

public bool DragAtAngle()
{
_endPoint = _startPoint;

_editor.PointMonitor +=
new PointMonitorEventHandler(Editor_PointMonitor);

try
{
//Get end point
if (GetEndPoint())
{
return true;
}
else
{
return false;
}
}
finally
{
ClearTransientGraphics();
_editor.PointMonitor -= Editor_PointMonitor;
}
}

#endregion

#region private methods

private void Editor_PointMonitor(
object sender, PointMonitorEventArgs e)
{
DrawDragLine(e.Context.RawPoint);
if (_dragLine != null)
{
e.AppendToolTipText("Angle: " +
_dragAngle.ToString() + "\nLength: " +
_dragLine.Length.ToString());
}
else
{
e.AppendToolTipText("");
}
}

private void DrawDragLine(Point3d mousePoint)
{
ClearTransientGraphics();

Point3d pt = CalculateEndPoint(mousePoint);

_dragLine = new Line(_startPoint, pt);
_dragLine.SetDatabaseDefaults(_db);
_dragLine.ColorIndex = _colorIndex;

IntegerCollection col = new IntegerCollection();
TransientManager.CurrentTransientManager.AddTransient(
_dragLine, TransientDrawingMode.Highlight, 128, col);

//whenever the dragged line updated, reset _endPoint
_endPoint = pt;
}

private void ClearTransientGraphics()
{
if (_dragLine != null)
{
IntegerCollection col = new IntegerCollection();
TransientManager.CurrentTransientManager.
EraseTransient(_dragLine, col);

_dragLine.Dispose();
_dragLine = null;
}
}

private Point3d CalculateEndPoint(Point3d mousePoint)
{
Point3d pt = mousePoint;

if (_dragAngle <= 90.0 || _dragAngle >= 270.0)
{
if (mousePoint.X <= _startPoint.X)
{
pt = _startPoint;
}
else
{
if (_dragAngle <= 45.0 || _dragAngle >= 315.0)
{
double y = (mousePoint.X - _startPoint.X) *
Math.Tan(_dragAngle * Math.PI / 180);
pt = new Point3d(
mousePoint.X, _startPoint.Y + y, 0.0);
}
else
{
if (_dragAngle > 45.0 && _dragAngle <= 90.0)
{
if (mousePoint.Y < _startPoint.Y)
{
pt = _startPoint;
}
else
{
double x = (mousePoint.Y - _startPoint.Y) /
Math.Tan(_dragAngle * Math.PI / 180);
pt = new Point3d(
_startPoint.X + x, mousePoint.Y, 0.0);
}
}
else
{
if (mousePoint.Y > _startPoint.Y)
{
pt = _startPoint;
}
else
{
double x = (mousePoint.Y - _startPoint.Y) /
Math.Tan(_dragAngle * Math.PI / 180);
pt = new Point3d(
_startPoint.X + x, mousePoint.Y, 0.0);
}
}
}

return pt;
}
}

if (_dragAngle >= 90.0 && _dragAngle <= 270.0)
{
if (mousePoint.X >= _startPoint.X)
{
pt = _startPoint;
}
else
{
if (_dragAngle >= 135.0 && _dragAngle <= 225.0)
{
double y = (mousePoint.X - _startPoint.X) *
Math.Tan(_dragAngle * Math.PI / 180);
pt = new Point3d(
mousePoint.X, _startPoint.Y + y, 0.0);
}
else
{
if (_dragAngle >=90.0 && _dragAngle < 135.0)
{
if (mousePoint.Y <= _startPoint.Y)
{
pt = _startPoint;
}
else
{
double x = (mousePoint.Y - _startPoint.Y) /
Math.Tan(_dragAngle * Math.PI / 180);
pt = new Point3d(
_startPoint.X + x, mousePoint.Y, 0.0);
}
}
else
{
if (mousePoint.Y >= _startPoint.Y)
{
pt = _startPoint;
}
else
{
double x = (mousePoint.Y - _startPoint.Y) /
Math.Tan(_dragAngle * Math.PI / 180);
pt = new Point3d(
_startPoint.X + x, mousePoint.Y, 0.0);
}
}

}

return pt;
}
}

return pt;
}

private bool GetEndPoint()
{
//endPoint = new Point3d();

bool go = true;
bool picked = false;

while (go)
{
PromptPointOptions opt = new PromptPointOptions("\nPick point:");
//opt.BasePoint = _startPoint;
//opt.UseBasePoint = true;
opt.Keywords.Add("Start point");
opt.Keywords.Add("Angle");
opt.Keywords.Add("End point");
opt.Keywords.Add("eXit");
opt.Keywords.Default = "End point";
opt.AppendKeywordsToMessage = true;
opt.AllowArbitraryInput = false;
opt.AllowNone = false;

PromptPointResult res = _editor.GetPoint(opt);
if (res.Status == PromptStatus.Cancel)
{
go = false; ;
}
else
{
switch (res.Status)
{
case PromptStatus.Keyword:
//_editor.WriteMessage("\n" + res.StringResult);
if (res.StringResult.StartsWith("Start"))
{
SetStartPoint();
go = true;
}
if (res.StringResult.StartsWith("Angle"))
{
SetAngle();
go = true;
}
if (res.StringResult.StartsWith("eXit"))
{
go = false;
}
break;
case PromptStatus.OK:
//endPoint = res.Value;
picked = true;
go = false;
break;
default:
go = true;
break;
}
}
}

return picked;
}

private void SetStartPoint()
{
ClearTransientGraphics();
_editor.PointMonitor -= Editor_PointMonitor;

PromptPointOptions opt =
new PromptPointOptions("\nStart point:");
PromptPointResult res = _editor.GetPoint(opt);
if (res.Status == PromptStatus.OK)
{
_startPoint = res.Value;
}

_editor.PointMonitor +=
new PointMonitorEventHandler(Editor_PointMonitor);
}

private void SetAngle()
{
ClearTransientGraphics();
_editor.PointMonitor -= Editor_PointMonitor;

PromptDoubleOptions opt =
new PromptDoubleOptions("\nEnter drag-angle in degree [" +
_dragAngle.ToString() + "]: ");
opt.AllowNegative = false;
opt.AllowZero = true;
opt.AllowNone = true;

PromptDoubleResult res = _editor.GetDouble(opt);

if (res.Status == PromptStatus.OK)
{
_dragAngle = res.Value;
if (_dragAngle > 360.0) _dragAngle -= 360.0;
}

_editor.PointMonitor +=
new PointMonitorEventHandler(Editor_PointMonitor);
}

#endregion
}
}

Here is the command class that uses the AngleLockedDrag class to draw a Line in AutoCAD.

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;

[assembly: CommandClass(typeof(AngleLockedDrag.DragCommand))]

namespace AngleLockedDrag
{
public class DragCommand
{
[CommandMethod("AngledDrag")]
public void RunThisMethod()
{
Document dwg = Autodesk.AutoCAD.ApplicationServices.
Application.DocumentManager.MdiActiveDocument;

AngledDrag drag = new AngledDrag(dwg);
try
{
if (drag.DragAtAngle())
{
GenerateLine(dwg, drag.StartPoint, drag.EndPoint);

dwg.Editor.WriteMessage("\nMyCommand executed.");
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
dwg.Editor.WriteMessage("\nError: {0}\n", ex.Message);
}
}

private static void GenerateLine(
Document dwg, Point3d startPt, Point3d endPt)
{
using (Transaction tran =
dwg.Database.TransactionManager.StartTransaction())
{
BlockTableRecord br = (BlockTableRecord)tran.GetObject(
dwg.Database.CurrentSpaceId, OpenMode.ForWrite);

Line line = new Line(startPt, endPt);
line.SetDatabaseDefaults(dwg.Database);

br.AppendEntity(line);
tran.AddNewlyCreatedDBObject(line, true);
tran.Commit();
}
}
}
}

Here is the video clip that shows the "angled dragging" effect.

Blog Archive

Labels

3D Modeling 3D Sketch Inventor AI Design AI in Manufacturing AI Tools Architecture Artificial Intelligence AutoCAD AutoCAD advice AutoCAD Basics AutoCAD Beginners AutoCAD Civil3D AutoCAD commands AutoCAD efficiency AutoCAD features AutoCAD File Management AutoCAD Layer AutoCAD learning AutoCAD print settings AutoCAD productivity AutoCAD Teaching AutoCAD Techniques AutoCAD tips AutoCAD training. AutoCAD tricks AutoCAD Tutorial AutoCAD workflow AutoCAD Xref Autodesk Autodesk 2025 Autodesk AI Tools Autodesk AutoCAD Autodesk Fusion 360 Autodesk Inventor Autodesk Inventor Frame Generator Autodesk Inventor iLogic Autodesk Recap Autodesk Revit Autodesk Software Autodesk Video Automation Automation Tutorial Basic Commands Basics Beginner Beginner Tips BIM BIM Implementation Block Editor ByLayer CAD comparison CAD Design CAD File Size Reduction CAD line thickness CAD Optimization CAD Productivity CAD software clean CAD file cleaning command Cloud Collaboration command abbreviations Construction Technology Contraints Create resizable blocks CTB STB Data Reference Data Shortcut design software Design Workflow Digital Design Digital Twin Drafting Standards Drawing Automation Dref Dynamic Block Dynamic Block AutoCAD Dynamic Blocks Dynamic doors Dynamic windows eco design editing commands energy efficiency Engineering Engineering Design Engineering Innovation Engineering Technology engineering tools Excel Express Tools External Reference Fast Structural Design Fusion 360 Generative Design green building Grips heavy CAD file Heavy CAD Files iLogic Industry 4.0 Insight Inventor API Inventor Drawing Template Inventor Frame Generator Inventor Graphics Issues Inventor IDW Inventor Tips Keyboard Shortcuts Learn AutoCAD Machine Learning in CAD maintenance command Management Manufacturing Innovation Metal Structure ObjectARX .NET API Organization OVERKILL OVERKILL AutoCAD Palette PDF Plot Style AutoCAD Practice Drawing Printing Quality professional printing Professional Tips PTC Creo PURGE PURGE AutoCAD ReCap reduce CAD file size Resizable Block Revit Revit Best Practices Revit Workflow Ribbon screen shortcut keys Shortcuts Siemens NX Sketch Small Firms Smart Block Smart Factory SolidWorks Steel Structure Design sustainability Sustainable Manufacturing toolbar Tutorial User Interface (UI) Workbook Workspace XLS Xref