The setup, im attempting to create mtext aligned to the selected object at the point nearest to where i select, this works fine for active objects, but is failing when it trys to calc the angle on nested objects (Line 106,
Dim
fder AsVector3d = bah.GetFirstDerivative(inspt)
) i think this is because the point is not associated with the cloned (from xref) object? any thoughts on how to get it to work with the single object selection/insertion point prompt? in the meantime ive re-written to have a second prompt for the insertion point, which works on the cloned object.
Heres the code:
Imports System Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.Geometry Imports Autodesk.AutoCAD.EditorInput <Assembly: CommandClass(GetType(Line_Labler.snibbity))> Namespace Line_Labler Public Class snibbity <CommandMethod("linelabel")> Public Sub snabble() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim peo As New PromptEntityOptions(vbCrLf & "Select Object at the Point to be labeled:") Dim per As PromptEntityResult = ed.GetEntity(peo) If per.Status = PromptStatus.OK Then Dim objId As ObjectId = per.ObjectId Dim dbo As Database = objId.Database Dim tr As Transaction = dbo.TransactionManager.StartTransaction() Using tr ' First get the currently selected object ' and check whether it's a block reference Dim br As BlockReference = TryCast(tr.GetObject(objId, OpenMode.ForRead), BlockReference) If br IsNot Nothing Then ' If so, we check whether the block table record ' to which it refers is actually from an XRef Dim btrId As ObjectId = br.BlockTableRecord Dim btr As BlockTableRecord = TryCast(tr.GetObject(btrId, OpenMode.ForRead), BlockTableRecord) ' If so, then we prigrammatically select the object ' underneath the pick-point already used Dim pneo As New PromptNestedEntityOptions("") pneo.NonInteractivePickPoint = per.PickedPoint pneo.UseNonInteractivePickPoint = True Dim pner As PromptNestedEntityResult = ed.GetNestedEntity(pneo) If pner.Status = PromptStatus.OK Then Dim obj As DBObject = tr.GetObject(pner.ObjectId, OpenMode.ForRead) Dim ent As Entity = DirectCast(obj, Entity) ' Clone the selected object Dim clob As Object = ent.Clone() Dim clone As Entity = TryCast(clob, Entity) If clone IsNot Nothing Then clone.SetPropertiesFrom(br) Dim lt As LayerTable = DirectCast(tr.GetObject(db.LayerTableId, OpenMode.ForRead), LayerTable) If lt.Has("C-VPRT") Then clone.LayerId = lt("C-VPRT") End If Dim conts As ObjectId() = pner.GetContainers() For Each contId As ObjectId In conts Dim cont As BlockReference = TryCast(tr.GetObject(contId, OpenMode.ForRead), BlockReference) If cont IsNot Nothing Then clone.TransformBy(cont.BlockTransform) End If Next Dim space As BlockTableRecord = TryCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord) 'If space Is Nothing Then ' clone.Dispose() ' Return 'End If Dim cloneId As ObjectId = space.AppendEntity(clone) tr.AddNewlyCreatedDBObject(clone, True) tr.TransactionManager.QueueForGraphicsFlush() End If Dim perpie = pner objactive(perpie) End If Else Dim perpie = per objactive(perpie) End If tr.Commit() End Using End If End Sub Private Sub objactive(ByVal perpie As Object) Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim vwtw = Application.GetSystemVariable("viewtwist") Dim meas As Integer = Application.GetSystemVariable("measurement") Application.SetSystemVariable("textstyle", "MKA Standard") Dim ansc = Application.GetSystemVariable("cannoscalevalue") Dim txht As Double If meas = 0 Then Application.SetSystemVariable("textsize", 0.125) Else Application.SetSystemVariable("textsize", 3.175) End If Using tr As Transaction = db.TransactionManager.StartTransaction Dim pso As New PromptStringOptions(vbCrLf & "Enter Text:") pso.AllowSpaces = True Dim psr As PromptResult = ed.GetString(pso) Dim inspt As Point3d Dim rotang As Double Dim radians As Double Dim degrees As Double Dim ent As Entity = tr.GetObject(perpie.ObjectId, OpenMode.ForRead) Dim obj As DBObject = tr.GetObject(perpie.ObjectId, OpenMode.ForRead) If TypeOf obj Is Curve Then Dim bah As Curve = TryCast(ent, Curve) 'Calc rotation at point inspt = bah.GetClosestPointTo(perpie.PickedPoint, True) Dim fder As Vector3d = bah.GetFirstDerivative(inspt) radians = Math.Truncate((Math.Atan2(CDbl(fder.Y), CDbl(fder.X)) + vwtw) * 100000000000) / 100000000000 degrees = Math.Round(radians * (180 / Math.PI), 5) 'check rotation If degrees = (0 Or 180 Or -180) Then rotang = 0 Else rotang = radians End If If degrees > 360 Then rotang = radians - (Math.PI * 2) degrees = Math.Round(rotang * (180 / Math.PI), 5) End If If (degrees > 90 And degrees <= 270) Or (degrees <= -90 And degrees >= -270) Then rotang = radians + Math.PI End If End If 'create mtext, apply rotation at point Dim bt As BlockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead) Dim btr As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite) Dim mt As MText = New MText mt.Annotative = AnnotativeStates.True mt.Location = inspt ed.WriteMessage(vbCrLf + "insertion point: " + mt.Location.ToString) mt.Attachment = AttachmentPoint.MiddleCenter mt.Rotation = rotang - vwtw mt.Contents = String.Concat(psr.StringResult, "\P ") mt.Height = txht btr.AppendEntity(mt) tr.AddNewlyCreatedDBObject(mt, True) tr.Commit() End Using End Sub End Class End Namespace
It's probably because the point isn't directly on the curve. Can you post a buildable sample project with a sample DWG file showing the problem please?
Fenton, attached is my source code and a few test files, i tweaked it a bit. all works fine in test 1, but test 2 it fails. i tracked the issue down a little better, it IS line 106, when debugging, returns "einvalid input" which i assume to mean the point i selected was not associated with the cloned object, or it throws the text at 0,0. compiled in .NET 4, testing in C3D 2013.
Hello Conor,
I think the issue is with the use of "per.ObjectId" in the "objactive" method.
This is the objectId of the entity in the xref and not the clone that was created.
When the pickedPoint is used to find the derivative of a curve from the Xref, invalid input exception gets thrown as the entity is not from the active database.
To see this behavior, you can try running the sample code in the attached file.
The only small change in the attached file is the commenting of the call to "objactive" method in case of nested entity selection.
When an entity in Xref is selected, only the clone of the curve gets created.
Run the command again and select the clone as you would with any regular non-xref curve.
So, to rectify the issue, you will need to use the clone curve to determine the derivative.
Hope this helps.
Balaji, that is exactly the problem, i was hoping someone had an idea on how to, i guess, re associate the picked point with the cloned object, if thats even possible. Otherwise i have a two-click solution (select object/clone, then select point) that works, but id rather use the single click.
You can transform a picked point into the coordinate system of a nested entity using the transformation obtained from the BlockReference.