Author Topic: Trying to insert block in current UCS  (Read 8432 times)

0 Members and 1 Guest are viewing this topic.

Patch61

  • Guest
Re: Trying to insert block in current UCS
« Reply #15 on: March 29, 2011, 01:16:25 PM »
Thanks for the help, guys!

Kaefer,

What language is that? It's almost basic, but Visual Studio doesn't like it.  :wink:

gile

  • Water Moccasin
  • Posts: 2234
  • Marseille, France
Re: Trying to insert block in current UCS
« Reply #16 on: March 29, 2011, 01:36:37 PM »
Quote
What language is that? It's almost basic, but Visual Studio doesn't like it.
It's F# and Visual Studio DO like it, it's part of Visual Studio 2010 and can be added to Visual Studio 2008 (not Express versions). See here.

kaefer,
It seems that your 'db.GetUcsMatrix' function returns the same as the native ed.CurrentUserCoordinateSystem().

Here's a C# code using the 'righter way'.

Code: [Select]
        [CommandMethod("TEST")]
        public void InsertInCurrentUcs()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptResult pr = ed.GetString("\nEnter the block name: ");
            if (pr.Status != PromptStatus.OK)
                return;
            string bName = pr.StringResult;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (!bt.Has(bName))
                {
                    ed.WriteMessage("\nCan't find '{0}' block.", bName);
                    return;
                }
                PromptPointResult ppr = ed.GetPoint("\nSpecify insertion point: ");
                if (ppr.Status != PromptStatus.OK)
                    return;
                Matrix3d ucsMat = ed.CurrentUserCoordinateSystem;
                BlockTableRecord btr =
                    (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                BlockReference br = new BlockReference(Point3d.Origin, bt[bName]);
                br.TransformBy(ucsMat * Matrix3d.Displacement(ppr.Value - Point3d.Origin));
                btr.AppendEntity(br);
                tr.AddNewlyCreatedDBObject(br, true);
                tr.Commit();
            }
        }
« Last Edit: March 29, 2011, 01:51:22 PM by gile »
Speaking English as a French Frog

Patch61

  • Guest
Re: Trying to insert block in current UCS
« Reply #17 on: March 29, 2011, 01:39:54 PM »
See here.

I assume that was supposed to be a link, but it's just bold. I have Visual Studio 2008 Standard.


gile

  • Water Moccasin
  • Posts: 2234
  • Marseille, France
Re: Trying to insert block in current UCS
« Reply #18 on: March 29, 2011, 01:54:50 PM »
Oopss !!!....
I add the link to the message, you can download F# 2.0 it will be added to VS standard.
Speaking English as a French Frog

kaefer

  • Swamp Rat
  • Posts: 572
Re: Trying to insert block in current UCS
« Reply #19 on: March 29, 2011, 02:39:58 PM »
kaefer,
It seems that your 'db.GetUcsMatrix' function returns the same as the native ed.CurrentUserCoordinateSystem().

Hi, gile.

Yeah, looks like it does. Wouldn't have thought that. Package label said:
Quote
Returns the current user coordinate system points.

Time to display a sheepish grin and stow away the much touted Database extension until there's no Editor to get a property of.

Patch61

  • Guest
Re: Trying to insert block in current UCS
« Reply #20 on: March 29, 2011, 02:47:19 PM »
Thanks for the help, guys. I'll try the new code out as soon as I get a chance.


Patch61

  • Guest
Re: Trying to insert block in current UCS
« Reply #21 on: March 30, 2011, 10:21:51 AM »
Gile,

I'm not having much luck integrating what you posted into the routine I posted. Some things just don't seem kosher. Like the Point3D.Origin you are using. Where is that from? I have the insertion point defined as iPt (using GetPoint), so I figured you meant to use that. But it won't let me use iPt.Origin, so I don't get what is going on. I guess if I knew enough to make your code work in my routine, I probably wouldn't have needed to ask for help in the first place.

Is there any chance you could slip your code into my routine? I need to insert a block from a file (checking to see if it already exists in the drawing) at the user-selected point, aligned with the current UCS. It also has to handle attributes.

I'm sure eventually this all will make sense, but right now, it doesn't. I feel like I am shooting in the dark here and I'm not hitting the target.


Thanks,
Steve
« Last Edit: March 30, 2011, 10:31:53 AM by Patch61 »

Jeff H

  • Needs a day job
  • Posts: 6055
Re: Trying to insert block in current UCS
« Reply #22 on: March 30, 2011, 10:44:53 AM »
Point3d.Origin is a read-only Shared(static for you C#) property of the Point3d

gile's code

Code: [Select]
                    Dim ucsMatrix As Matrix3d = ed.CurrentUserCoordinateSystem
                    Dim bref As New BlockReference(Point3d.Origin)
                    bref.TransformBy(ucsMatrix * Matrix3d.Displacement(iPt - Point3d.Origin))

Jeff H

  • Needs a day job
  • Posts: 6055
Re: Trying to insert block in current UCS
« Reply #23 on: March 30, 2011, 10:51:06 AM »
This is it from reflector

Code: [Select]
Public Shared ReadOnly Property Origin As Point3d
    Get
        Return New Point3d(0, 0, 0)
    End Get
End Property
 

Patch61

  • Guest
Re: Trying to insert block in current UCS
« Reply #24 on: March 30, 2011, 10:51:55 AM »
Point3d.Origin is a read-only Shared(static for you C#) property of the Point3d

gile's code

Code: [Select]
                    Dim ucsMatrix As Matrix3d = ed.CurrentUserCoordinateSystem
                    Dim bref As New BlockReference(Point3d.Origin)
                    bref.TransformBy(ucsMatrix * Matrix3d.Displacement(iPt - Point3d.Origin))

I understand what it is, I don't understand his use of a property of something that has not been assigned a value. That is why I asked where it is from. And, like I mentioned, I don't understand why it wouldn't let me use iPt.Origin in its place. I'm beginning to think I'm missing some basic thing here and that is causing me confusion.


gile

  • Water Moccasin
  • Posts: 2234
  • Marseille, France
Re: Trying to insert block in current UCS
« Reply #25 on: March 30, 2011, 12:25:55 PM »
Origin is a static (Shared) property of the Point3d class, that means it cannot be used with instances of this class.
Point3d.Origin is a kind of constant equivalent to : new Point3d(0.0, 0.0, 0.0).

In the code I posted (inspired by kaefer's one) the block reference is first inserted in 0, 0, 0 and then tranformed by a matix which is a combination of the UCS matrix and a displacement (vector) from 0, 0, 0 ti iPt so that the block refrence is rotate and displaced about the UCS and then displaced from the UCS origin to the specified insertion point.
Speaking English as a French Frog

Jeff H

  • Needs a day job
  • Posts: 6055
Re: Trying to insert block in current UCS
« Reply #26 on: March 30, 2011, 12:43:44 PM »
Vb will let you use a shared a member with a instance of a the class it just generates a warning.
This will complie ans run but with warnings
Code: [Select]
                    Dim pointOrgin As New Point3d(0.0, 0.0, 0.0)
                    Dim pnt As Point3d = pointOrgin.Origin

                    Dim pointy As Point3d

                    Dim ucsMatrix As Matrix3d = ed.CurrentUserCoordinateSystem

                    Dim bref As New BlockReference(pointy.Origin, bt("BlockName"))

                    bref.TransformBy(ucsMatrix * Matrix3d.Displacement(pnt - pnt.Origin))

Each instance of the class does not get it own copy of a shared member. It is "class wide" or each instance "shares" hence Shared.
The property has been assinged and is assigned at the class level as read-only.
A good reason or example for using a shared property is to a count how many instances of a class have been created.

Jeff H

  • Needs a day job
  • Posts: 6055
Re: Trying to insert block in current UCS
« Reply #27 on: March 30, 2011, 01:31:26 PM »
I think MS thinking is accessing a static property through the Class name instead of a instance makes your code harder to read, but in way a way is seems natural to be able to access it through a instance since it is meant to be "shared".

Patch61

  • Guest
Re: Trying to insert block in current UCS
« Reply #28 on: March 30, 2011, 03:52:37 PM »
OK, no matter what I do, this is failing. It fails if the block exists, and it fails for a different reason if the block is loaded from disk. I don't know what I am doing wrong.

Code: [Select]
      Public Sub InsertDrawingAsBlock(ByVal doc As Document, ByVal path As String, ByVal blockname As String, _
                                      ByVal iPt As Point3d, Optional ByVal Space As String = "Model", _
                                      Optional ByVal LayerName As String = "Misc", Optional ByVal Xplode As Boolean = False, _
                                      Optional ByVal bRotate As Double = 0.0, Optional ByVal bXScale As Single = 1.0, _
                                      Optional ByVal bYScale As Single = 1.0, Optional ByVal bZScale As Single = 1.0)
         Dim curdb As Database = doc.Database
         Dim ed As Editor = doc.Editor
         Dim loc As DocumentLock = doc.LockDocument()
         Using loc
            Dim blkid As ObjectId = ObjectId.Null
            Dim db As Database = doc.Database
            Using db
               db.ReadDwgFile(path, System.IO.FileShare.Read, True, "")
               blkid = curdb.Insert(path, db, True)
               Using tr As Transaction = db.TransactionManager.StartTransaction()
                  Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
                  Dim ucsMat As Matrix3d = ed.CurrentUserCoordinateSystem
                  Dim btr As BlockTableRecord = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
                  If bt.Has(blockname) Then
                     Dim br As New BlockReference(Point3d.Origin, bt(blockname))
                     br.TransformBy(ucsMat * Matrix3d.Displacement(iPt - Point3d.Origin))
                     Dim btrId As ObjectId = bt(blockname).GetObject(OpenMode.ForRead).ObjectId
                     btr.UpgradeOpen()
                     btr.AppendEntity(br)
                     tr.AddNewlyCreatedDBObject(br, True)
                  Else
                     bt.UpgradeOpen()
                     'Dim br As New BlockReference(Point3d.Origin, bt(blockname))
                     'br.TransformBy(ucsMat * Matrix3d.Displacement(iPt - Point3d.Origin))
                     Dim btrec As BlockTableRecord = DirectCast(blkid.GetObject(OpenMode.ForRead), BlockTableRecord)
                     btrec.UpgradeOpen()
                     btrec.Name = blockname
                     btrec.DowngradeOpen()

                     Using btr
                        Using bref As New BlockReference(iPt, blkid)
                           'Rotate 45 degrees
                           '45 * (Math.PI/180)
                           bref.Rotation = bRotate * (Math.PI / 180)
                           'Scale factor
                           bref.ScaleFactors = New Scale3d(bXScale, bYScale, bZScale)
                           bref.TransformBy(ucsMat * Matrix3d.Displacement(iPt - Point3d.Origin))
                           btr.AppendEntity(bref)

                           tr.AddNewlyCreatedDBObject(bref, True)

                           Using btAttRec As BlockTableRecord = DirectCast(bref.BlockTableRecord.GetObject(OpenMode.ForRead), BlockTableRecord)
                              Dim atcoll As Autodesk.AutoCAD.DatabaseServices.AttributeCollection = bref.AttributeCollection
                              For Each subid As ObjectId In btAttRec
                                 Dim ent As Entity = DirectCast(subid.GetObject(OpenMode.ForRead), Entity)
                                 Dim attDef As AttributeDefinition = TryCast(ent, AttributeDefinition)
                                 If attDef IsNot Nothing Then
                                    Dim attRef As New AttributeReference()
                                    attRef.SetPropertiesFrom(attDef)
                                    attRef.Visible = attDef.Visible
                                    attRef.SetAttributeFromBlock(attDef, bref.BlockTransform)
                                    attRef.HorizontalMode = attDef.HorizontalMode
                                    attRef.VerticalMode = attDef.VerticalMode
                                    attRef.Rotation = attDef.Rotation
                                    attRef.TextStyleId = attDef.TextStyleId
                                    attRef.Position = attDef.Position + iPt.GetAsVector()
                                    attRef.Tag = attDef.Tag
                                    attRef.FieldLength = attDef.FieldLength
                                    attRef.TextString = attDef.TextString
                                    attRef.AdjustAlignment(curdb)
                                    atcoll.AppendAttribute(attRef)
                                    tr.AddNewlyCreatedDBObject(attRef, True)
                                 End If
                              Next
                           End Using
                           bref.DowngradeOpen()

                           'Does it need to be exploded?
                           If Xplode = True Then
                              bref.ExplodeToOwnerSpace()
                              bref.Erase()
                           End If

                        End Using
                     End Using
                     btrec.DowngradeOpen()
                     bt.DowngradeOpen()
                     ed.Regen()

                  End If
                  tr.Commit()
               End Using
            End Using
         End Using
      End Sub

Jeff H

  • Needs a day job
  • Posts: 6055
Re: Trying to insert block in current UCS
« Reply #29 on: March 30, 2011, 04:04:44 PM »
Dim curdb As Database = doc.Database

  Dim db As Database = doc.Database
            Using db
               db.ReadDwgFile(path, System.IO.FileShare.Read, True, "")


Just looking real quick you are using the same database from whatever doc is passed in as a parameter
You need to create a new database before you call ReadDwgFile