000

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