.NET

Reply
Valued Contributor
Ron_M
Posts: 75
Registered: ‎12-09-2013
Message 1 of 13 (195 Views)
Accepted Solution

Rotate Prior to Insertion of Block

195 Views, 12 Replies
05-02-2014 08:00 AM

ACA 2014, WIndows 7 64, VS 2013 Express, VB.Net

 

The block library is coming along well and I'm at a point where one further push or assist should allow me to complete it.

 

At this time blocks are pulled from external drawings, shown on the cursor as it moves on the screen, rotate on the cursor prior to input, BUT insert at the original orientation.  I am confused on how to pass back to InsertBlock the rotation angle of the block as shown on the cursor and have the block inserted at that orienation rather than at the original.  Below are the code for my library and the jig. 

 

Library.vb

Imports System
Imports System.IO
Imports System.Windows.Controls
Imports Autodesk.AutoCAD
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime

Public Class Library
    Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
    Dim itemstr As String
    Dim ed As Editor

    Private Sub Library_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        For Each i As String In Directory.GetDirectories("R:\2014\Library\")
            ListView1.Items.Add(Path.GetFileName(i))
        Next
        ListView1.Items.Remove(ListView1.Items(0))
        If ListView1.Items.Count > 0 Then
            ListView1.Items(0).Focused = True
            ListView1.Items(0).Selected = True
            itemstr = (Me.ListView1.FocusedItem.Text)
            PictureBox1.ImageLocation = ("R:\2014\Library\" & itemstr & "\template.wmf")
        End If
    End Sub

    Private Sub ListView1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListView1.SelectedIndexChanged
        If Me.ListView1.SelectedItems.Count > 0 Then
            itemstr = (Me.ListView1.FocusedItem.Text)
            PictureBox1.ImageLocation = ("R:\2014\Library\" & itemstr & "\template.wmf")
        End If
    End Sub

    Private Sub PictureBox1_MouseClick(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseClick
        Dim xPos As Integer
        Dim yPos As Integer
        If e.Button = System.Windows.Forms.MouseButtons.Left Then
            xPos = e.X
            yPos = e.Y
        End If
        doit(xPos, yPos, itemstr)
    End Sub

    Private Sub doit(ByVal xPos As Single, ByVal yPos As Single, itemstr As String)
        Dim box As String
        Dim x As Integer
        Dim y As Integer
        Dim layer As String
        x = (Int(xPos / 100))
        y = (Int(yPos / 100))
        If y > 0 Then
            box = (Int((x) + (Int(y) * 8)))
        Else : box = x
        End If

        'Layers
        Using Myreader As New Microsoft.VisualBasic.FileIO.TextFieldParser("R:\2014\Library\" & itemstr & "\layers.lst")
            Myreader.TextFieldType = FileIO.FieldType.Delimited
            Myreader.SetDelimiters(",")
            While Not Myreader.EndOfData
                Try
                    Dim fields() As String = Myreader.ReadFields
                    layer = (fields(box))
                Finally
                End Try
            End While
            AddLayer(layer)
        End Using

        'Blocks
        Using Myreaderblocks As New Microsoft.VisualBasic.FileIO.TextFieldParser("R:\2014\Library\" & itemstr & "\library.lst")
            Myreaderblocks.TextFieldType = FileIO.FieldType.Delimited
            Myreaderblocks.SetDelimiters(",")
            While Not Myreaderblocks.EndOfData
                Try
                    Dim fields() As String = Myreaderblocks.ReadFields
                    Dim currentField As String = (fields(box))
                    If currentField.Length > 5 Then
                        result = currentField.Substring(currentField.Length - 3)
                    End If
                    Dim BlockName As String = currentField.Substring(0, currentField.Length - 6)
                    If Not result = "" Then
                        Select Case result
                            Case "dwg"
                                addblock(BlockName, currentField, itemstr)
                        End Select
                    End If
                Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
                End Try
            End While
        End Using
    End Sub

    Public Sub AddLayer(layer)
        Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Dim ed As Editor = doc.Editor
        acDoc.LockDocument()
        Using tr As Transaction = db.TransactionManager.StartTransaction()
            Dim ltb As LayerTable = DirectCast(tr.GetObject(db.LayerTableId, OpenMode.ForRead), LayerTable)
            'create a new layer
            If Not ltb.Has(layer) Then
                ltb.UpgradeOpen()
                Dim newLayer As New LayerTableRecord()
                newLayer.Name = layer
                newLayer.LineWeight = LineWeight.LineWeight005
                newLayer.Description = "This is new layer"
                'red color
                newLayer.Color = Autodesk.AutoCAD.Colors.Color.FromRgb(255, 0, 0)
                ltb.Add(newLayer)
                tr.AddNewlyCreatedDBObject(newLayer, True)
            End If
            tr.Commit()
            'make it as current
            db.Clayer = ltb(layer)
        End Using
    End Sub

    Public Sub addblock(ByVal blockname As String, ByVal currentfield As String, ByVal itemstr As String)
        Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
        Using OpenDb As New Database(False, True)
            OpenDb.ReadDwgFile("R:\2014\Library\" & itemstr & "\" & currentfield, System.IO.FileShare.ReadWrite, True, "")
            acDoc.LockDocument()
            Dim ids As New ObjectIdCollection()
            Using tr As Transaction = OpenDb.TransactionManager.StartTransaction()
                'For example, Get the block by name "BlkName"
                Dim bt As BlockTable
                bt = DirectCast(tr.GetObject(OpenDb.BlockTableId, OpenMode.ForRead), BlockTable)
                If bt.Has(blockname) Then
                    ids.Add(bt(blockname))
                End If
                tr.Commit()
            End Using
            'if not found, add the block
            If ids.Count <> 0 Then
                'get the current drawing database
                Dim destdb As Database = acDoc.Database
                Dim iMap As New IdMapping()
                acDoc.LockDocument()
                destdb.WblockCloneObjects(ids, destdb.BlockTableId, iMap, DuplicateRecordCloning.Ignore, False)
            End If
        End Using
        Dispose()
        InsertBlockWithJig(blockname, layer)
    End Sub

    Public Sub InsertBlockWithJig(ByVal blockname As String, layer As String)
        Dim myDB As Database
        myDB = HostApplicationServices.WorkingDatabase
        Dim myJig As BlockJig

        Using myTrans As Transaction = myDB.TransactionManager.StartTransaction
            Dim myBT As BlockTable = myDB.BlockTableId.GetObject(OpenMode.ForRead)
            If myBT.Has(blockname) Then
                Dim myBTR As BlockTableRecord = myBT(blockname).GetObject(OpenMode.ForRead)
                myJig = New BlockJig(myBTR.ObjectId)
            Else
                Exit Sub
            End If
        End Using
        Dim myBlkID As ObjectId
        Dim SelPt As EditorInput.PromptPointResult
        Dim pdr As EditorInput.PromptPointResult
        Do
            SelPt = myJig.BeginJig
            If Not SelPt Is Nothing Then
                Select Case SelPt.Status
                    Case EditorInput.PromptStatus.OK
                        myBlkID = insertblock(SelPt.Value, blockname)
                    Case EditorInput.PromptStatus.Other
                        Exit Sub
                End Select
            End If
            If SelPt Is Nothing Then Exit Do
        Loop While SelPt.Status = EditorInput.PromptStatus.OK
    End Sub

    Public Function insertblock(BasePt As Point3d, blockname As String)
        Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
        Using myT As Transaction = db.TransactionManager.StartTransaction()
            'Get the block definition "Check".
            Dim bt As BlockTable = TryCast(db.BlockTableId.GetObject(OpenMode.ForRead), BlockTable)
            Dim blockDef As BlockTableRecord = TryCast(bt(blockname).GetObject(OpenMode.ForRead), BlockTableRecord)
            'Also open modelspace - we'll be adding our BlockReference to it
            Dim ms As BlockTableRecord = TryCast(bt(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite), BlockTableRecord)

            'Create new BlockReference, and link it to our block definition
            Using blockRef As New BlockReference(BasePt, blockDef.ObjectId)
                'Add the block reference to modelspace
                ms.AppendEntity(blockRef)
                myT.AddNewlyCreatedDBObject(blockRef, True)

                'Iterate block definition to find all non-constant AttributeDefinitions
                For Each id As ObjectId In blockDef
                    Dim obj As DBObject = id.GetObject(OpenMode.ForRead)
                    Dim attDef As AttributeDefinition = TryCast(obj, AttributeDefinition)
                    If (attDef IsNot Nothing) AndAlso (Not attDef.Constant) Then
                        'This is a non-constant AttributeDefinition
                        'Create a new AttributeReference
                        Using attRef As New AttributeReference()
                            attRef.SetAttributeFromBlock(attDef, blockRef.BlockTransform)
                            'Add the AttributeReference to the BlockReference
                            blockRef.AttributeCollection.AppendAttribute(attRef)
                            myT.AddNewlyCreatedDBObject(attRef, True)
                        End Using
                    End If
                Next
            End Using
            acDoc.TransactionManager.QueueForGraphicsFlush()
            myT.Commit()
        End Using
    End Function

End Class

 BlockJig.vb

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD

Public Class BlockJig
    Inherits Autodesk.AutoCAD.EditorInput.EntityJig
    Dim BasePt As Point3d = New Point3d(0, 0, 0)
    Dim myMatrix As Matrix3d
    Dim myBRef As DatabaseServices.BlockReference
    Dim myOpts As EditorInput.JigPromptPointOptions
    Dim CurrentKeyword As String
    Protected _pos As Point3d
    Protected _rot As Double, _ucsRot As Double

    Sub New(ByVal BlockID As ObjectId)
        MyBase.New(New DatabaseServices.BlockReference(BlockIns, BlockID))
        myBRef = Me.Entity
        _pos = myBRef.Position
        _rot = myBRef.Rotation
    End Sub

    Function BeginJig() As PromptPointResult
        If myOpts Is Nothing Then
            myOpts = New EditorInput.JigPromptPointOptions()
            myOpts.Message = vbCrLf & "Select a point:"
            myOpts.Cursor = EditorInput.CursorType.Invisible
            myOpts.UseBasePoint = False
        End If
        Dim ed As EditorInput.Editor = Application.DocumentManager.MdiActiveDocument.Editor
        Dim myPR As PromptResult
        Dim ucs As CoordinateSystem3d = ed.CurrentUserCoordinateSystem.CoordinateSystem3d
        Dim ocsMat As Matrix3d = Matrix3d.WorldToPlane(New Plane(Point3d.Origin, ucs.Zaxis))
        _ucsRot = Vector3d.XAxis.GetAngleTo(ucs.Xaxis.TransformBy(ocsMat), ucs.Zaxis)
        _rot = myBRef.Rotation - _ucsRot
        myPR = ed.Drag(Me)
        Do
            Select Case myPR.Status
                Case EditorInput.PromptStatus.OK
                    Return myPR
                    Exit Do
                Case EditorInput.PromptStatus.None
                    Return myPR
                    Exit Do
                Case EditorInput.PromptStatus.Other
                    Return myPR
                    Exit Do
            End Select
        Loop While myPR.Status <> EditorInput.PromptStatus.Cancel
        Return Nothing
    End Function

    Protected Overrides Function Sampler(prompts As JigPrompts) As SamplerStatus
        Dim mods As System.Windows.Forms.Keys = System.Windows.Forms.Control.ModifierKeys
        If (mods And System.Windows.Forms.Keys.Control) > 0 Then
            Dim jpao As New JigPromptAngleOptions(vbLf & "Specify the rotation: ")
            jpao.UseBasePoint = True
            jpao.BasePoint = myBRef.Position
            jpao.Cursor = CursorType.Invisible
            jpao.UserInputControls = (UserInputControls.Accept3dCoordinates Or UserInputControls.UseBasePointElevation)
            Dim pdr As PromptDoubleResult = prompts.AcquireAngle(jpao)

            If _rot = pdr.Value Then
                Return SamplerStatus.NoChange
            Else
                _rot = pdr.Value
                Return SamplerStatus.OK
            End If
        Else
            Dim jppo As New JigPromptPointOptions(vbLf & "Specify insertion point (or press Ctrl for rotation): ")
            jppo.UserInputControls = (UserInputControls.Accept3dCoordinates Or UserInputControls.NullResponseAccepted)
            Dim ppr As PromptPointResult = prompts.AcquirePoint(jppo)
            If _pos.DistanceTo(ppr.Value) < Tolerance.[Global].EqualPoint Then
                Return SamplerStatus.NoChange
            Else
                _pos = ppr.Value
            End If
            Return SamplerStatus.OK
        End If
    End Function

    Protected Overrides Function Update() As Boolean
        myBRef.Position = _pos
        myBRef.Rotation = _rot + _ucsRot
        Return True
    End Function

End Class

 

One more step further.

Using a class which implements the System.Windows.Forms.IMessageFilter interface allows to catch some key down during the jig drag and perform some changes to the block rotation.
In the following sample, it's used to add 90° to the block current rotation each time the user hits the Tab key.

 

using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
namespace InsertBlockSample
{
public class CommandMethods
{
[CommandMethod("Test")]
public void Test()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
PromptResult psr = ed.GetString("\nEnter the block name: ");
if (psr.Status != PromptStatus.OK) return;
string blockName = psr.StringResult;
InsertBlock(blockName);
}
private void InsertBlock(string blockName)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
if (bt.Has(blockName))
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
using (BlockReference br = new BlockReference(Point3d.Origin, bt[blockName]))
{
br.TransformBy(ed.CurrentUserCoordinateSystem);
BlockTableRecord curspace =
(BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
curspace.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
BlockJig jig;
if (btr.HasAttributeDefinitions)
{
Dictionary<string, TextInfo> attInfos = new Dictionary<string, TextInfo>();
RXClass attribClass = RXClass.GetClass(typeof(AttributeDefinition));
foreach (ObjectId id in btr)
{
if (id.ObjectClass == attribClass)
{
AttributeDefinition attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
AttributeReference attRef = new AttributeReference();
attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
br.AttributeCollection.AppendAttribute(attRef);
tr.AddNewlyCreatedDBObject(attRef, true);
attInfos.Add(attDef.Tag, new TextInfo(attDef));
}
}
jig = new BlockAttribJig(br, attInfos);
}
else
{
jig = new BlockJig(br);
}
TabKeyDownFilter tabFilter = new TabKeyDownFilter(jig);
System.Windows.Forms.Application.AddMessageFilter(tabFilter);
PromptResult pr = ed.Drag(jig);
if (pr.Status != PromptStatus.OK)
{
br.Erase();
}
System.Windows.Forms.Application.RemoveMessageFilter(tabFilter);
}
}
else
{
Application.ShowAlertDialog(string.Format("Block '{0}' not found.", blockName));
}
tr.Commit();
}
}
}
class BlockJig : EntityJig
{
protected BlockReference br;
protected Point3d pos;
protected double ucsRot;
protected internal double Rotation { get; set; }
public BlockJig(BlockReference br)
: base(br)
{
this.br = br;
pos = br.Position;
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Matrix3d ucsMat = ed.CurrentUserCoordinateSystem;
CoordinateSystem3d ucs = ucsMat.CoordinateSystem3d;
Matrix3d ocsMat = Matrix3d.WorldToPlane(new Plane(Point3d.Origin, ucs.Zaxis));
ucsRot = Vector3d.XAxis.GetAngleTo(ucs.Xaxis.TransformBy(ocsMat), ucs.Zaxis);
this.Rotation = br.Rotation - ucsRot;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
System.Windows.Forms.Keys mods = System.Windows.Forms.Control.ModifierKeys;
if ((mods & System.Windows.Forms.Keys.Control) > 0)
{
JigPromptAngleOptions jpao = new JigPromptAngleOptions(
"\nSpecify the rotation (release Ctrl to validate): ");
jpao.UseBasePoint = true;
jpao.BasePoint = br.Position;
jpao.Cursor = CursorType.RubberBand;
jpao.UserInputControls = (
UserInputControls.Accept3dCoordinates |
UserInputControls.UseBasePointElevation);
PromptDoubleResult pdr = prompts.AcquireAngle(jpao);
if (this.Rotation == pdr.Value)
{
return SamplerStatus.NoChange;
}
else
{
this.Rotation = pdr.Value;
return SamplerStatus.OK;
}
}
else
{
JigPromptPointOptions jppo = new JigPromptPointOptions(
"\nSpecify the insertion point (or press Ctrl for rotation): ");
jppo.UserInputControls =
(UserInputControls.Accept3dCoordinates |
UserInputControls.NullResponseAccepted);
PromptPointResult ppr = prompts.AcquirePoint(jppo);
if (pos.DistanceTo(ppr.Value) < Tolerance.Global.EqualPoint)
{
return SamplerStatus.NoChange;
}
else
{
pos = ppr.Value;
}
return SamplerStatus.OK;
}
}
protected override bool Update()
{
br.Position = pos;
UpdateRotation();
return true;
}
internal void UpdateRotation()
{
br.Rotation = this.Rotation + ucsRot;
}
}
class BlockAttribJig : BlockJig
{
private Dictionary<string, TextInfo> attRefInfos;
private Transaction tr;
public BlockAttribJig(BlockReference br, Dictionary<string, TextInfo> attInfos)
: base(br)
{
attRefInfos = attInfos;
tr = br.Database.TransactionManager.TopTransaction;
}
protected override bool Update()
{
base.Update();
foreach (ObjectId id in br.AttributeCollection)
{
AttributeReference att = (AttributeReference)tr.GetObject(id, OpenMode.ForWrite);
string tag = att.Tag.ToUpper();
if (attRefInfos.ContainsKey(tag))
{
TextInfo ti = attRefInfos[tag];
att.Position = ti.Position.TransformBy(br.BlockTransform);
att.Rotation = ti.Rotation + br.Rotation;
if (ti.IsAligned)
{
att.AlignmentPoint =
ti.Alignment.TransformBy(br.BlockTransform);
att.AdjustAlignment(br.Database);
}
if (att.IsMTextAttribute)
{
att.UpdateMTextAttribute();
}
}
}
return true;
}
}
struct TextInfo
{
public readonly Point3d Position, Alignment;
public readonly bool IsAligned;
public readonly double Rotation;
public TextInfo(DBText text)
{
this.Position = text.Position;
this.Alignment = text.AlignmentPoint;
this.IsAligned = text.Justify != AttachmentPoint.BaseLeft;
this.Rotation = text.Rotation;
}
}
class TabKeyDownFilter : System.Windows.Forms.IMessageFilter
{
private const int WM_KEYDOWN = 0x100;
private BlockJig jig;
public TabKeyDownFilter(BlockJig jig)
{
this.jig = jig;
}
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_KEYDOWN && (int)m.WParam == 9)
{
jig.Rotation += Math.PI / 2.0;
jig.UpdateRotation();
}
return false;
}
}
}

 

*Expert Elite*
_gile
Posts: 2,133
Registered: ‎04-29-2006
Message 2 of 13 (183 Views)

Re : Rotate Prior to Insertion of Block

05-02-2014 08:28 AM in reply to: Ron_M

Hi,

 

You can add a Rotation property in the BlockJig class so that you can get the specified rotation from the calling method and set this rotation to the inserted BlockReference.

Gilles Chanteau
Valued Contributor
Ron_M
Posts: 75
Registered: ‎12-09-2013
Message 3 of 13 (179 Views)

Re : Rotate Prior to Insertion of Block

05-02-2014 08:37 AM in reply to: _gile
I had thought I had done that as I can rotate the block on the cursor prior to selecting the insertion point. I can't seem to get the rotation returned to the inserted block.
*Expert Elite*
_gile
Posts: 2,133
Registered: ‎04-29-2006
Message 4 of 13 (164 Views)

Re : Rotate Prior to Insertion of Block

05-03-2014 05:28 AM in reply to: Ron_M

Hi,

 

I didn't read your code enough attentively.

 

Here's a little sample closer to my understanding of your request (the code don't care about loading the block if not existing in the block table to focus to the  BlockJig).

 

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

namespace InsertBlockSample
{
    public class CommandMethods
    {
        [CommandMethod("Test")]
        public void Test()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptResult psr = ed.GetString("\nEnter the block name: ");
            if (psr.Status != PromptStatus.OK) return;
            string blockName = psr.StringResult;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (bt.Has(blockName))
                {
                    using (BlockReference br = new BlockReference(Point3d.Origin, bt[blockName]))
                    {
                        br.TransformBy(ed.CurrentUserCoordinateSystem);
                        BlockJig jig = new BlockJig(br);
                        PromptResult pr = ed.Drag(jig);
                        if (pr.Status == PromptStatus.OK)
                        {
                            BlockTableRecord curspace =
                                (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                            curspace.AppendEntity(br);
                            tr.AddNewlyCreatedDBObject(br, true);
                        }
                    }
                }
                else
                {
                    Application.ShowAlertDialog(string.Format("Block '{0}' not found.", blockName));
                }
                tr.Commit();
            }
        }
    }

    class BlockJig : EntityJig
    {
        protected BlockReference _br;
        protected Point3d _pos;
        protected double _rot, _ucsRot;

        public BlockJig(BlockReference br)
            : base(br)
        {
           _br = br;
            _pos = br.Position;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Matrix3d ucsMat = ed.CurrentUserCoordinateSystem;
            CoordinateSystem3d ucs = ucsMat.CoordinateSystem3d;
            Matrix3d ocsMat = Matrix3d.WorldToPlane(new Plane(Point3d.Origin, ucs.Zaxis));
            _ucsRot = Vector3d.XAxis.GetAngleTo(ucs.Xaxis.TransformBy(ocsMat), ucs.Zaxis);
            _rot = br.Rotation - _ucsRot;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            System.Windows.Forms.Keys mods = System.Windows.Forms.Control.ModifierKeys;
            if ((mods & System.Windows.Forms.Keys.Control) > 0)
            {
                JigPromptAngleOptions jpao = new JigPromptAngleOptions(
                    "\nSpecify the rotation (release Ctrl to validate): ");
                jpao.UseBasePoint = true;
                jpao.BasePoint = _br.Position;
                jpao.Cursor = CursorType.RubberBand;
                jpao.UserInputControls = (
                    UserInputControls.Accept3dCoordinates |
                    UserInputControls.UseBasePointElevation);
                PromptDoubleResult pdr = prompts.AcquireAngle(jpao);

                if (_rot == pdr.Value)
                {
                    return SamplerStatus.NoChange;
                }
                else
                {
                    _rot = pdr.Value;
                    return SamplerStatus.OK;
                }
            }
            else
            {
                JigPromptPointOptions jppo = new JigPromptPointOptions(
                    "\nSpecify the insertion point (or press Ctrl for rotation): ");
                jppo.UserInputControls =
                  (UserInputControls.Accept3dCoordinates |
                  UserInputControls.NullResponseAccepted);
                PromptPointResult ppr = prompts.AcquirePoint(jppo);
                if (_pos.DistanceTo(ppr.Value) < Tolerance.Global.EqualPoint)
                {
                    return SamplerStatus.NoChange;
                }
                else
                {
                    _pos = ppr.Value;
                }
                return SamplerStatus.OK;
            }
        }

        protected override bool Update()
        {
            _br.Position = _pos;
            _br.Rotation = _rot + _ucsRot;
            return true;
        }
    }
}

 

Gilles Chanteau
*Expert Elite*
_gile
Posts: 2,133
Registered: ‎04-29-2006
Message 5 of 13 (153 Views)

Re : Rotate Prior to Insertion of Block

05-03-2014 01:40 PM in reply to: _gile

One step further.

 

If the block have attributes and you want to diplay them during the jig dragging, you may add the block reference and the attribute references before dragging and erase it if ed.Drag(jig) does not return PromptStatus.OK

I use another class (BlockAttribJig) which inherits from BlockJig and only cares of updating the attributes geometry.

I also use a little structure (AttInfo) to store the text informations of the attribute definitions.

 

using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace InsertBlockSample
{
    public class CommandMethods
    {
        [CommandMethod("Test")]
        public void Test()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;  

            PromptResult psr = ed.GetString("\nEnter the block name: ");
            if (psr.Status != PromptStatus.OK) return;
            string blockName = psr.StringResult;

            InsertBlock(blockName);
        }

        private void InsertBlock(string blockName)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (bt.Has(blockName))
                {
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
                    using (BlockReference br = new BlockReference(Point3d.Origin, bt[blockName]))
                    {
                        br.TransformBy(ed.CurrentUserCoordinateSystem);
                        BlockTableRecord curspace =
                            (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                        curspace.AppendEntity(br);
                        tr.AddNewlyCreatedDBObject(br, true);

                        BlockJig jig;
                        if (btr.HasAttributeDefinitions)
                        {
                            Dictionary<string, TextInfo> attInfos = new Dictionary<string, TextInfo>();
                            RXClass attribClass = RXClass.GetClass(typeof(AttributeDefinition));
                            foreach (ObjectId id in btr)
                            {
                                if (id.ObjectClass == attribClass)
                                {
                                    AttributeDefinition attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
                                    AttributeReference attRef = new AttributeReference();
                                    attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
                                    br.AttributeCollection.AppendAttribute(attRef);
                                    tr.AddNewlyCreatedDBObject(attRef, true);
                                    attInfos.Add(attDef.Tag, new TextInfo(attDef));
                                }
                            }
                            jig = new BlockAttribJig(br, attInfos);
                        }
                        else
                        {
                            jig = new BlockJig(br);
                        }

                        PromptResult pr = ed.Drag(jig);
                        if (pr.Status != PromptStatus.OK)
                        {
                            br.Erase();
                        }
                    }
                }
                else
                {
                    Application.ShowAlertDialog(string.Format("Block '{0}' not found.", blockName));
                }
                tr.Commit();
            }
        }
    }

    class BlockJig : EntityJig
    {
        protected BlockReference br;
        protected Point3d pos;
        protected double ucsRot, rot;

        public BlockJig(BlockReference br)
            : base(br)
        {
            this.br = br;
            pos = br.Position;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Matrix3d ucsMat = ed.CurrentUserCoordinateSystem;
            CoordinateSystem3d ucs = ucsMat.CoordinateSystem3d;
            Matrix3d ocsMat = Matrix3d.WorldToPlane(new Plane(Point3d.Origin, ucs.Zaxis));
            ucsRot = Vector3d.XAxis.GetAngleTo(ucs.Xaxis.TransformBy(ocsMat), ucs.Zaxis);
            rot = br.Rotation - ucsRot;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            System.Windows.Forms.Keys mods = System.Windows.Forms.Control.ModifierKeys;
            if ((mods & System.Windows.Forms.Keys.Control) > 0)
            {
                JigPromptAngleOptions jpao = new JigPromptAngleOptions(
                    "\nSpecify the rotation (release Ctrl to validate): ");
                jpao.UseBasePoint = true;
                jpao.BasePoint = br.Position;
                jpao.Cursor = CursorType.RubberBand;
                jpao.UserInputControls = (
                    UserInputControls.Accept3dCoordinates |
                    UserInputControls.UseBasePointElevation);
                PromptDoubleResult pdr = prompts.AcquireAngle(jpao);

                if (rot == pdr.Value)
                {
                    return SamplerStatus.NoChange;
                }
                else
                {
                    rot = pdr.Value;
                    return SamplerStatus.OK;
                }
            }
            else
            {
                JigPromptPointOptions jppo = new JigPromptPointOptions(
                    "\nSpecify the insertion point (or press Ctrl for rotation): ");
                jppo.UserInputControls =
                  (UserInputControls.Accept3dCoordinates |
                  UserInputControls.NullResponseAccepted);
                PromptPointResult ppr = prompts.AcquirePoint(jppo);
                if (pos.DistanceTo(ppr.Value) < Tolerance.Global.EqualPoint)
                {
                    return SamplerStatus.NoChange;
                }
                else
                {
                    pos = ppr.Value;
                }
                return SamplerStatus.OK;
            }
        }

        protected override bool Update()
        {
            br.Position = pos;
            br.Rotation = rot + ucsRot;
            return true;
        }
    }

    class BlockAttribJig : BlockJig
    {
        private Dictionary<string, TextInfo> attRefInfos;
        private Transaction tr;

        public BlockAttribJig(BlockReference br, Dictionary<string, TextInfo> attInfos)
            : base(br)
        {
            attRefInfos = attInfos;
            tr = br.Database.TransactionManager.TopTransaction;
        }

        protected override bool Update()
        {
            base.Update();
            foreach (ObjectId id in br.AttributeCollection)
            {
                AttributeReference att = (AttributeReference)tr.GetObject(id, OpenMode.ForWrite);
                string tag = att.Tag.ToUpper();
                if (attRefInfos.ContainsKey(tag))
                {
                    TextInfo ti = attRefInfos[tag];
                    att.Position = ti.Position.TransformBy(br.BlockTransform);
                    att.Rotation = ti.Rotation + br.Rotation;
                    if (ti.IsAligned)
                    {
                        att.AlignmentPoint =
                            ti.Alignment.TransformBy(br.BlockTransform);
                        att.AdjustAlignment(br.Database);
                    }
                    if (att.IsMTextAttribute)
                    {
                        att.UpdateMTextAttribute();
                    }
                }
            }
            return true;
        }
    }

    struct TextInfo
    {
        public readonly Point3d Position, Alignment;
        public readonly bool IsAligned;
        public readonly double Rotation;

        public TextInfo(DBText text)
        {
            this.Position = text.Position;
            this.Alignment = text.AlignmentPoint;
            this.IsAligned = text.Justify != AttachmentPoint.BaseLeft;
            this.Rotation = text.Rotation;
        }
    }
}

 

 

 

Gilles Chanteau
*Expert Elite*
_gile
Posts: 2,133
Registered: ‎04-29-2006
Message 6 of 13 (147 Views)

Re : Rotate Prior to Insertion of Block

05-03-2014 02:21 PM in reply to: _gile

One more step further.

Using a class which implements the System.Windows.Forms.IMessageFilter interface allows to catch some key down during the jig drag and perform some changes to the block rotation.
In the following sample, it's used to add 90° to the block current rotation each time the user hits the Tab key.

 

using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace InsertBlockSample
{
    public class CommandMethods
    {
        [CommandMethod("Test")]
        public void Test()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;  

            PromptResult psr = ed.GetString("\nEnter the block name: ");
            if (psr.Status != PromptStatus.OK) return;
            string blockName = psr.StringResult;

            InsertBlock(blockName);
        }

        private void InsertBlock(string blockName)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (bt.Has(blockName))
                {
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
                    using (BlockReference br = new BlockReference(Point3d.Origin, bt[blockName]))
                    {
                        br.TransformBy(ed.CurrentUserCoordinateSystem);
                        BlockTableRecord curspace =
                            (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                        curspace.AppendEntity(br);
                        tr.AddNewlyCreatedDBObject(br, true);

                        BlockJig jig;
                        if (btr.HasAttributeDefinitions)
                        {
                            Dictionary<string, TextInfo> attInfos = new Dictionary<string, TextInfo>();
                            RXClass attribClass = RXClass.GetClass(typeof(AttributeDefinition));
                            foreach (ObjectId id in btr)
                            {
                                if (id.ObjectClass == attribClass)
                                {
                                    AttributeDefinition attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
                                    AttributeReference attRef = new AttributeReference();
                                    attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
                                    br.AttributeCollection.AppendAttribute(attRef);
                                    tr.AddNewlyCreatedDBObject(attRef, true);
                                    attInfos.Add(attDef.Tag, new TextInfo(attDef));
                                }
                            }
                            jig = new BlockAttribJig(br, attInfos);
                        }
                        else
                        {
                            jig = new BlockJig(br);
                        }

                        TabKeyDownFilter tabFilter = new TabKeyDownFilter(jig);
                        System.Windows.Forms.Application.AddMessageFilter(tabFilter);
                        PromptResult pr = ed.Drag(jig);
                        if (pr.Status != PromptStatus.OK)
                        {
                            br.Erase();
                        }
                        System.Windows.Forms.Application.RemoveMessageFilter(tabFilter);
                    }
                }
                else
                {
                    Application.ShowAlertDialog(string.Format("Block '{0}' not found.", blockName));
                }
                tr.Commit();
            }
        }
    }

    class BlockJig : EntityJig
    {
        protected BlockReference br;
        protected Point3d pos;
        protected double ucsRot;

        protected internal double Rotation { get; set; }

        public BlockJig(BlockReference br)
            : base(br)
        {
            this.br = br;
            pos = br.Position;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Matrix3d ucsMat = ed.CurrentUserCoordinateSystem;
            CoordinateSystem3d ucs = ucsMat.CoordinateSystem3d;
            Matrix3d ocsMat = Matrix3d.WorldToPlane(new Plane(Point3d.Origin, ucs.Zaxis));
            ucsRot = Vector3d.XAxis.GetAngleTo(ucs.Xaxis.TransformBy(ocsMat), ucs.Zaxis);
            this.Rotation = br.Rotation - ucsRot;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            System.Windows.Forms.Keys mods = System.Windows.Forms.Control.ModifierKeys;
            if ((mods & System.Windows.Forms.Keys.Control) > 0)
            {
                JigPromptAngleOptions jpao = new JigPromptAngleOptions(
                    "\nSpecify the rotation (release Ctrl to validate): ");
                jpao.UseBasePoint = true;
                jpao.BasePoint = br.Position;
                jpao.Cursor = CursorType.RubberBand;
                jpao.UserInputControls = (
                    UserInputControls.Accept3dCoordinates |
                    UserInputControls.UseBasePointElevation);
                PromptDoubleResult pdr = prompts.AcquireAngle(jpao);

                if (this.Rotation == pdr.Value)
                {
                    return SamplerStatus.NoChange;
                }
                else
                {
                    this.Rotation = pdr.Value;
                    return SamplerStatus.OK;
                }
            }
            else
            {
                JigPromptPointOptions jppo = new JigPromptPointOptions(
                    "\nSpecify the insertion point (or press Ctrl for rotation): ");
                jppo.UserInputControls =
                  (UserInputControls.Accept3dCoordinates |
                  UserInputControls.NullResponseAccepted);
                PromptPointResult ppr = prompts.AcquirePoint(jppo);
                if (pos.DistanceTo(ppr.Value) < Tolerance.Global.EqualPoint)
                {
                    return SamplerStatus.NoChange;
                }
                else
                {
                    pos = ppr.Value;
                }
                return SamplerStatus.OK;
            }
        }

        protected override bool Update()
        {
            br.Position = pos;
            UpdateRotation();
            return true;
        }

        internal void UpdateRotation()
        {
            br.Rotation = this.Rotation + ucsRot;
        }
    }

    class BlockAttribJig : BlockJig
    {
        private Dictionary<string, TextInfo> attRefInfos;
        private Transaction tr;

        public BlockAttribJig(BlockReference br, Dictionary<string, TextInfo> attInfos)
            : base(br)
        {
            attRefInfos = attInfos;
            tr = br.Database.TransactionManager.TopTransaction;
        }

        protected override bool Update()
        {
            base.Update();
            foreach (ObjectId id in br.AttributeCollection)
            {
                AttributeReference att = (AttributeReference)tr.GetObject(id, OpenMode.ForWrite);
                string tag = att.Tag.ToUpper();
                if (attRefInfos.ContainsKey(tag))
                {
                    TextInfo ti = attRefInfos[tag];
                    att.Position = ti.Position.TransformBy(br.BlockTransform);
                    att.Rotation = ti.Rotation + br.Rotation;
                    if (ti.IsAligned)
                    {
                        att.AlignmentPoint =
                            ti.Alignment.TransformBy(br.BlockTransform);
                        att.AdjustAlignment(br.Database);
                    }
                    if (att.IsMTextAttribute)
                    {
                        att.UpdateMTextAttribute();
                    }
                }
            }
            return true;
        }
    }

    struct TextInfo
    {
        public readonly Point3d Position, Alignment;
        public readonly bool IsAligned;
        public readonly double Rotation;

        public TextInfo(DBText text)
        {
            this.Position = text.Position;
            this.Alignment = text.AlignmentPoint;
            this.IsAligned = text.Justify != AttachmentPoint.BaseLeft;
            this.Rotation = text.Rotation;
        }
    }

    class TabKeyDownFilter : System.Windows.Forms.IMessageFilter
    {
        private const int WM_KEYDOWN = 0x100;
        private BlockJig jig;

        public TabKeyDownFilter(BlockJig jig)
        {
            this.jig = jig;
        }

        public bool PreFilterMessage(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_KEYDOWN && (int)m.WParam == 9)
            {
                jig.Rotation += Math.PI / 2.0;
                jig.UpdateRotation();
            }
            return false;
        }
    }
}

 

Gilles Chanteau
Valued Contributor
Ron_M
Posts: 75
Registered: ‎12-09-2013
Message 7 of 13 (124 Views)

Re : Rotate Prior to Insertion of Block

05-05-2014 03:31 AM in reply to: _gile
Thanks for all of the input. I'm going to start digesting this morning and will follow up soon.
Valued Contributor
Ron_M
Posts: 75
Registered: ‎12-09-2013
Message 8 of 13 (114 Views)

Re : Rotate Prior to Insertion of Block

05-05-2014 03:58 AM in reply to: _gile

And now I know why you are an "Expert Elite".  Many thanks for this.  I'm going to try to get back the modeless library window and multiple insertion on my own.  Had it previously so I don't think that will be difficult.  Again, if I could upgrade your rating I would.

Valued Contributor
Ron_M
Posts: 75
Registered: ‎12-09-2013
Message 9 of 13 (101 Views)

Re : Rotate Prior to Insertion of Block

05-05-2014 11:21 AM in reply to: _gile

At this time I am unable to visually see the attributes in the blocks during or after insertion.  I've gone back to a point where I had that working but am so far I have proven inadequate to integrating it into the block insertion with rotate with attInfos.  The attributes are there in the block, the blocks haven't changed in construction, I can attedit the attributes, but I can't see them.  Any ideas?

*Expert Elite*
_gile
Posts: 2,133
Registered: ‎04-29-2006
Message 10 of 13 (98 Views)

Re : Rotate Prior to Insertion of Block

05-05-2014 11:47 AM in reply to: Ron_M

Did you add the block reference and its attributes to the current space and the transaction before dragging the block?

Gilles Chanteau
Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Do you have 60 seconds to spare? The Autodesk Community Team is revamping our site ranking system and we want your feedback! Please click here to launch the 5 question survey. As always your input is greatly appreciated.