Do you use vb.net or c# draw a polyline with arrow using EntityJig which allows you to change the direction of the arrow as shown below
Due to the fact that work often has to use arrows, if you can draw and drag the desired arrow direction as above, it will be very effective for the job.
Solved! Go to Solution.
Solved by quyenpv. Go to Solution.
Solved by _gile. Go to Solution.
Are you offering to share your code?? If so, post it in a code window using the </> button.
Either language will get the job done. If you are just starting out and haven't learned either language then it is recommended to use C#. The majority of examples posted are written in C#.
Hi,
Before embarking on such a task, you should first learn how to simply acquire a user start and end point and draw an arrow-shaped polyline in the current space.
Using classes derived from EntityJig to dynamically display entity modifications based on cursor position requires a mastery of the basic concepts of AutoCAD's .NET API.
@_gile Please help fix it
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Public Class ArrowJig
Inherits EntityJig
Private _startPoint As Point3d
Private _arrowEnd As Point3d
Public Sub New(entity As Entity, startPt As Point3d)
MyBase.New(entity)
_startPoint = startPt
_arrowEnd = startPt
End Sub
Protected Overrides Function Sampler(prompts As JigPrompts) As SamplerStatus
Dim jppo As New JigPromptPointOptions("Chọn điểm kết thúc mũi tên:")
jppo.BasePoint = _startPoint
jppo.UseBasePoint = True
Dim res = prompts.AcquirePoint(jppo)
If res.Value.Equals(_arrowEnd) Then
Return SamplerStatus.NoChange
Else
_arrowEnd = res.Value
Return SamplerStatus.OK
End If
End Function
Protected Overrides Function Update() As Boolean
Dim polyline As Polyline = TryCast(Me.Entity, Polyline)
If polyline IsNot Nothing Then
Dim dir = _arrowEnd - _startPoint
Dim arrowLen = dir.Length / 3
Dim perp = dir.GetPerpendicularVector().GetNormal() * arrowLen / 2
dir = dir.GetNormal()
polyline.SetPointAt(0, New Point2d(_startPoint.X, _startPoint.Y))
polyline.SetPointAt(1, New Point2d(_arrowEnd.X, _arrowEnd.Y))
polyline.SetPointAt(2, New Point2d((_arrowEnd - (dir * arrowLen)).X, (_arrowEnd - (dir * arrowLen)).Y))
polyline.SetPointAt(3, New Point2d((_arrowEnd - (dir * arrowLen) + perp).X, (_arrowEnd - (dir * arrowLen) + perp).Y))
End If
Return True
End Function
Public Shared Sub CreateArrow()
Dim doc = Application.DocumentManager.MdiActiveDocument
Dim db = doc.Database
Dim ed = doc.Editor
Dim ppr = ed.GetPoint("Chọn điểm bắt đầu mũi tên:")
If ppr.Status <> PromptStatus.OK Then
Return
End If
Dim polyline As New Polyline()
polyline.AddVertexAt(0, New Point2d(ppr.Value.X, ppr.Value.Y), 0, 0, 0)
polyline.AddVertexAt(1, New Point2d(ppr.Value.X, ppr.Value.Y), 0, 0, 0)
polyline.AddVertexAt(2, New Point2d(ppr.Value.X, ppr.Value.Y), 0, 0, 0)
Dim jig As New ArrowJig(polyline, ppr.Value)
Dim res = ed.Drag(jig)
If res.Status = PromptStatus.OK Then
Using tr = db.TransactionManager.StartTransaction()
Dim btr As BlockTableRecord = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite)
btr.AppendEntity(polyline)
tr.AddNewlyCreatedDBObject(polyline, True)
tr.Commit()
End Using
End If
End Sub
End Class
#Region "Test Commands"
Public Module TestArrow
<CommandMethod("TestArrow")>
Public Sub CreateArrowCmd()
ArrowJig.CreateArrow()
End Sub
End Module
#End Region
Hi Quyen,
Here's the update, but as Mr.Gile said "Don't try to run before you're able to stand up".
Protected Overrides Function Update() As Boolean
Dim polyline As Polyline = TryCast(Me.Entity, Polyline)
If polyline IsNot Nothing Then
Dim dir = _arrowEnd - _startPoint
Dim arrowLen = dir.Length / 3
Dim perp = dir.GetPerpendicularVector().GetNormal() * arrowLen / 2
dir = dir.GetNormal()
polyline.SetPointAt(0, New Point2d(_startPoint.X, _startPoint.Y))
polyline.SetPointAt(1, New Point2d((_arrowEnd - (dir * arrowLen)).X, (_arrowEnd - (dir * arrowLen)).Y))
polyline.SetStartWidthAt(1, arrowLen / 2)
polyline.SetPointAt(2, New Point2d(_arrowEnd.X, _arrowEnd.Y))
'polyline.SetPointAt(3, New Point2d((_arrowEnd - (dir * arrowLen) + perp).X, (_arrowEnd - (dir * arrowLen) + perp).Y))
End If
Return True
End Function
Thank you @GiaBach , @_gile
The above code after updating still can't drag the arrow direction after drawing like the picture
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Public Class ArrowJig
Inherits EntityJig
Private _startPoint As Point3d
Private _arrowEnd As Point3d
Public Sub New(entity As Entity, startPt As Point3d)
MyBase.New(entity)
_startPoint = startPt
_arrowEnd = startPt
End Sub
Protected Overrides Function Sampler(prompts As JigPrompts) As SamplerStatus
Dim jppo As New JigPromptPointOptions("Chọn điểm kết thúc mũi tên:")
jppo.BasePoint = _startPoint
jppo.UseBasePoint = True
Dim res = prompts.AcquirePoint(jppo)
If res.Value.Equals(_arrowEnd) Then
Return SamplerStatus.NoChange
Else
_arrowEnd = res.Value
Return SamplerStatus.OK
End If
End Function
Protected Overrides Function Update() As Boolean
Dim polyline As Polyline = TryCast(Me.Entity, Polyline)
If polyline IsNot Nothing Then
Dim dir = _arrowEnd - _startPoint
Dim arrowLen = dir.Length / 3
Dim perp = dir.GetPerpendicularVector().GetNormal() * arrowLen / 2
dir = dir.GetNormal()
polyline.SetPointAt(0, New Point2d(_startPoint.X, _startPoint.Y))
polyline.SetPointAt(1, New Point2d((_arrowEnd - (dir * arrowLen)).X, (_arrowEnd - (dir * arrowLen)).Y))
polyline.SetStartWidthAt(1, arrowLen / 2)
polyline.SetPointAt(2, New Point2d(_arrowEnd.X, _arrowEnd.Y))
'polyline.SetPointAt(3, New Point2d((_arrowEnd - (dir * arrowLen) + perp).X, (_arrowEnd - (dir * arrowLen) + perp).Y))
End If
Return True
End Function
Public Shared Sub CreateArrow()
Dim doc = Application.DocumentManager.MdiActiveDocument
Dim db = doc.Database
Dim ed = doc.Editor
Dim ppr = ed.GetPoint("Chọn điểm bắt đầu mũi tên:")
If ppr.Status <> PromptStatus.OK Then
Return
End If
Dim polyline As New Polyline()
polyline.AddVertexAt(0, New Point2d(ppr.Value.X, ppr.Value.Y), 0, 0, 0)
polyline.AddVertexAt(1, New Point2d(ppr.Value.X, ppr.Value.Y), 0, 0, 0)
polyline.AddVertexAt(2, New Point2d(ppr.Value.X, ppr.Value.Y), 0, 0, 0)
Dim jig As New ArrowJig(polyline, ppr.Value)
Dim res = ed.Drag(jig)
If res.Status = PromptStatus.OK Then
Using tr = db.TransactionManager.StartTransaction()
Dim btr As BlockTableRecord = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite)
btr.AppendEntity(polyline)
tr.AddNewlyCreatedDBObject(polyline, True)
tr.Commit()
End Using
End If
End Sub
End Class
#Region "Test Commands"
Public Module TestArrow
<CommandMethod("TestArrow")>
Public Sub CreateArrowCmd()
ArrowJig.CreateArrow()
End Sub
End Module
#End Region
Did you write this code yourself? Because it seems to have been written by a ChatGPT (i.e., an assembly of code snippets that it doesn't understand but that seems to answer the request).
It seems that you don't want to follow the recommendations you've been given to learn how to program AutoCAD.
@quyenpv a écrit :
This code I wrote myself and concatenated many reference codes on the forums
This is the same way ChatGPT tries to predict what a code responding to a request might be, and most of the time the code doesn't work.
If you really want to learn programming, write code step by step.
First write simple command to draw an arrow from the start point to the end point (note you can use the polyline width for the arrow head).
Second write another simple command for the reversed arrow (arrow head on the start point).
Finally you could try to write a code using a Jig to switch the side of the arrow head according to the cursor position.
Learning is an extension of the whole process. Crossing martial arts is too difficult
Học là một sự trải dài của cả quá trình. Vượt vũ môn khó quá
Now that we know how to draw the arrow in both directions, we can separate the part of the code that draws the base polyline and the part that draws the arrowhead, and execute the latter part with a Jig to let the user choose the direction.
The command method:
The ArrowJig class
Thank you very much @_gile
Through your code, I really understand its essence
Code full C# of @_gile
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
[assembly: CommandClass(typeof(ArrowCommands))]
public class ArrowCommands
{
[CommandMethod("Arrow3")]
public static void DrawArrow()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptPointOptions ppo = new PromptPointOptions("\nStart point:");
PromptPointResult ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK) return;
Point3d point1 = ppr.Value;
ppo.Message = "\nEnd point:";
ppo.UseBasePoint = true;
ppo.BasePoint = ppr.Value;
ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK) return;
Point3d point2 = ppr.Value;
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
using (Polyline pline = new Polyline())
{
Point2d startPoint = new Point2d(point1.X, point1.Y);
Point2d endPoint = new Point2d(point2.X, point2.Y);
pline.AddVertexAt(0, startPoint, 0.0, 0.0, 0.0);
pline.AddVertexAt(1, endPoint, 0.0, 0.0, 0.0);
pline.TransformBy(ed.CurrentUserCoordinateSystem);
// Using a jig to set the arrow head
ArrowJig jig = new ArrowJig(pline);
PromptResult jigResult = ed.Drag(jig);
if (jigResult.Status == PromptStatus.OK)
{
BlockTableRecord curSpace = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
curSpace.AppendEntity(pline);
tr.AddNewlyCreatedDBObject(pline, true);
}
}
tr.Commit();
}
}
}
class ArrowJig : EntityJig
{
private Polyline pline;
private Point3d dragPoint;
private Point2d startPoint, endPoint;
private Vector2d vector;
private double width;
public ArrowJig(Polyline pline) : base(pline)
{
this.pline = pline;
startPoint = pline.GetPoint2dAt(0);
endPoint = pline.GetPoint2dAt(1);
vector = startPoint.GetVectorTo(endPoint) / 3.0;
width = pline.Length / 6.0;
pline.AddVertexAt(1, endPoint - vector, 0.0, width, 0.0);
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
PromptPointResult promptPointResult = prompts.AcquirePoint("\nPick a point on the arrowhead side:");
if (promptPointResult.Value.IsEqualTo(dragPoint))
return SamplerStatus.NoChange;
dragPoint = promptPointResult.Value;
return SamplerStatus.OK;
}
protected override bool Update()
{
if (dragPoint.DistanceTo(startPoint) < dragPoint.DistanceTo(endPoint))
{
pline.SetPointAt(1, startPoint + vector);
pline.SetEndWidthAt(0, width);
pline.SetStartWidthAt(1, 0.0);
}
else
{
pline.SetPointAt(1, endPoint - vector);
pline.SetEndWidthAt(0, 0.0);
pline.SetStartWidthAt(1, width);
}
return true;
}
}
Can't find what you're looking for? Ask the community or share your knowledge.