Author Topic: ObjectIDs from DXF 330 entries in XRecords  (Read 4476 times)

0 Members and 1 Guest are viewing this topic.

dgorsman

  • Water Moccasin
  • Posts: 2437
ObjectIDs from DXF 330 entries in XRecords
« on: July 15, 2013, 01:59:32 PM »
I'm storing soft pointer references in XRecords using DXF 330:

Code: [Select]
(list
   (cons 330 "196")
)

It takes a string value with the handle of the object.  When its read back, it comes as a safearray of type long with two values:

Code: [Select]
[0] -9415968
[1] -44994284

Neither of these are acceptable to ObjectIDToObject or ObjectIDToObject32 which are necessary to convert the ObjectID to something useable, such as a handle, entity ID, or vla-object.  GetObjectIDString won't work, as it requires the object in the first place.  This worked previously with x32, so I'm thinking theres some extra steps needed to be added for x64.

Any thoughts?
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

Gasty

  • Newt
  • Posts: 90
Re: ObjectIDs from DXF 330 entries in XRecords
« Reply #1 on: July 15, 2013, 03:52:01 PM »
Hi,

In my understand, objectids are no persistent and has meaning only inside a transaction, why not use just the handles as a soft pointers? they are almost immutable and are unique inside the same database, so a pair {dwg,handle} can be considered as a key for any object with a handle.

Gaston Nunez

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: ObjectIDs from DXF 330 entries in XRecords
« Reply #2 on: July 15, 2013, 03:56:33 PM »
This needs to be persistent between sessions.  The 330 group is used for soft-pointer handle storage, returning ObjectIDs rather than the original string value (handle).  Granted, I could store the value as a hard coded string but I'd like to use the DXF value types as intended.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

Lee Mac

  • Seagull
  • Posts: 12915
  • London, England
Re: ObjectIDs from DXF 330 entries in XRecords
« Reply #3 on: July 15, 2013, 05:51:32 PM »
According to the documentation, I was under the understanding that DXF 320-329 should be used for entity handles, with DXF 330-369 reserved for object IDs:

Code: [Select]
320-329 String representing hex handle value
330-369 String representing hex object IDs

Granted, I use XRecords infrequently.

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: ObjectIDs from DXF 330 entries in XRecords
« Reply #4 on: July 15, 2013, 06:21:51 PM »
More completely:

Code: [Select]
320-329: Arbitrary object handles; handle values that are taken “as is”. They are not translated during INSERT and XREF operations

330-339: Soft-pointer handle; arbitrary soft pointers to other objects within same DXF file or drawing. Translated during INSERT and XREF operations
 


Note they both refer to "handles".  I've done it successfuly with the 330-series in the past where the returned pointer will accurately translate with the (vla-ObjectIDToObject ...) prior to working with x64 AutoCAD.  I should be able to get away with using the 320-series in this specific circumstance, but there are other cases where that handle translation will be required to handle XREF ie. handles are translated to not overlap with the host drawing content.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: ObjectIDs from DXF 330 entries in XRecords
« Reply #5 on: July 15, 2013, 11:58:13 PM »
if you look at the numbers being returned they are both Int32, I'm guessing if you combine them together into a single Int64 value that will likely give you the value you're after. 

CADDOG

  • Newt
  • Posts: 82
  • wishbonesr
Re: ObjectIDs from DXF 330 entries in XRecords
« Reply #6 on: July 16, 2013, 02:24:01 PM »
More completely:

Quote
320-329: Arbitrary object handles; handle values that are taken “as is”. They are not translated during INSERT and XREF operations

330-339: Soft-pointer handle; arbitrary soft pointers to other objects within same DXF file or drawing. Translated during INSERT and XREF operations
 


Note they both refer to "handles".  I've done it successfuly with the 330-series in the past where the returned pointer will accurately translate with the (vla-ObjectIDToObject ...) prior to working with x64 AutoCAD.  I should be able to get away with using the 320-series in this specific circumstance, but there are other cases where that handle translation will be required to handle XREF ie. handles are translated to not overlap with the host drawing content.

I see where you're coming from.  And I see the contradictions in terminology.  My online help differs from my local help.  My local help matches the cusomization guide going all the way back to R13 (physical books).  None the less... Lee is right.   This is an ename/objectid.
(entget) any block and look at the the 330 slot.  Regardless of the terminology, it's an ename (in autolisp); Always has been.

Persistent Inter-Object Reference Handles (DXF)
dxf 1005 may be more appropriate for handles.

Seems like you were here once before.

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: ObjectIDs from DXF 330 entries in XRecords
« Reply #7 on: July 16, 2013, 02:52:38 PM »
DXF 1005 is for XDATA, rather than XRecords.  In some cases the entity code is needed rather than the handle.  Consider an XRecord attached to an object from an XREF (or inserted as a block) instead of the host drawing.  The raw handle from a 320 series won't be translated, so its value is based on the referenced file rather than the current one - trying to get the object based on that handle will almost certainly return the wrong object.  The return of an entity code/ID from the 330 series ensures the proper translation of that handle value so it is refering to the proper entity.  The ObjectID *should* be convertable back to a handle or object.

I'll have to fiddle with the high byte/low byte theory later - right now I've got to smack around some Civil3D templates and styles.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

CADDOG

  • Newt
  • Posts: 82
  • wishbonesr
Re: ObjectIDs from DXF 330 entries in XRecords
« Reply #8 on: July 17, 2013, 08:27:05 PM »
I hear ya.  Bad suggestion on 1005...  And wouldn't want to start telling you what direction to go in; 

The ObjectID *should* be convertable back to a handle or object.

Provided you store an ename/objectID in the first place... and not a handle (as your post clearly indicates).  I can only speculate why it worked before (that is, storing a handle)... Perhaps a translation was occuring.  I have both a 32 and 64, and I can't store a handle in those code ranges.  If I try storing a handle as a dxf 330, I get.
Quote
; error: bad DXF group: (331 . "27E")

...fiddle with the high byte/low byte theory...
Saw this and this, but couldn't figure it out.  Not big on math and bit shifting.

This needs to be persistent between sessions.
Object ID's in the 330 range are.  They change, but autocad sorts out all the references and all 330 ranges, etc. at load time.  I know that's a contradiction in terms (again), none the less, the dynamic nature of the id's combined with 330 series can derive the persistant handles you seek.

The 330 group is used for soft-pointer handle storage, returning ObjectIDs rather than the original string value (handle).
I know some docs say handle, but this is a terminology clash.  It doesn't store handles and return objectids.  No Way Jose.  Stores objectids/ename -> returns objectids/ename.  entget the returned ename, and you'll get the correct object every time.  If you want the handle, then get that after the entget.  (cdr (assoc 5 (entget (car (_refobjID)))))

I get the results you describe you want with current dwg, xref, and block insert or block insert explode, using the following quick xrecord write (see next code). 
NOTE: If storing in namedobjectdict, it (custom dict) doesn't make it into the dwg it is being inserted into; So I stored on a line object extended dict.

As far as xref.  Using nentsel, the handle of the objects in the xref are the same as the source drawing.   They don't get their own handles when being xref'd.  However the 330 objectid does corrently resolve to the corrent entity in the reffing dwg, and of course acts as an inserted block described above, when xref-bind-insert, etc.

I go about creating the xrecord and dict a little unconventionaly, so sorry for the code vomit.  But this shows me the 330 range works on both 32 & 64 bit IF using objectids/enames.


NOTE:  I tested by using a circle and a line.
Code: [Select]
(setq prmpref "Select object you want to reference"
      prmpstor "Select object you want to store the information on"
      prmpget "Select object you want to retrieve information from")
;make
;using 331 because it's more simple to find
(setq EanXrec (entmakex (list '(0 . "XRECORD")
     '(100 . "AcDbXrecord")
     (cons 331 (car (entsel prmpref))))))
(setq line (vlax-ename->vla-object (car (entsel prmpstor))))
(setq extdic (vla-getextensiondictionary line))
(setq Eextdic(vlax-vla-object->ename extdic))
(dictadd Eextdic "MYDIC" EanXrec)

;read in current drawing
(setq extdic (vla-getextensiondictionary (vlax-ename->vla-object (car (entsel prmpget)))))
(setq Eextdic (vlax-vla-object->ename extdic))
(setq Eanxrec (cdr (assoc -1 (dictsearch Eextdic "MYDIC"))))
(setq recobj (entget Eanxrec))
(setq Eref (cdr (assoc 331 recobj)))
(setq refobj (entget eref))

;read in xrefing drawing or bind-insert or inserted block.
(setq extdic (vla-getextensiondictionary (vlax-ename->vla-object (car (nentsel prmpget)))))
(setq Eextdic (vlax-vla-object->ename extdic))
(setq Eanxrec (cdr (assoc -1 (dictsearch Eextdic "MYDIC"))))
(setq recobj (entget Eanxrec))
(setq Eref (cdr (assoc 331 recobj)))
(setq refobj (entget eref))

;handle test
;run on reference object before inserting or on exploded block objects on new drawing
(setq handle (cdr (assoc 5 (entget (car (entsel))))))
;run on inserted block object (unexploded)
(setq handle (cdr (assoc 5 (entget (car (nentsel))))))

Attached are the files I used to experiment.  Drawing2.dwg contains a crapload of rectangls, to ensure no chance of coincidence in the handles being the same with a fresh acad.dwt.
« Last Edit: July 17, 2013, 10:39:51 PM by CADDOG »