Author Topic: Change xref type ( overlay / attach ) and getting the xclip boundary [ beta ]  (Read 8352 times)

0 Members and 1 Guest are viewing this topic.

T.Willey

  • Needs a day job
  • Posts: 5251
Here is code that I came up with yesterday.  I was just trying to get the xclip boundary, but then I went a step further and made it so you could change the type from overlay to attach, and vice versa.  This is still in beta form, as I have only tested it with xrefs added in WCS, and only with one xref per, but I did check it with an xref whose path was not saved, and was not in the search path, and it found said xref file.  The only problem is, is that it sets the xref path to the file path, and not just the file name like it was stored, so that might be an item to fix.  I haven't tested it was relative pathing either.  Post any comments / ideas / whatever.

Code: [Select]
(defun GetSpatialFilter (ename / Data Dict tempDict)
    ; Get the xclip boundry
   
    (if
        (and
            (setq Data (entget ename))
            (setq Dict (cdr (assoc 360 Data)))
            (setq tempDict (dictsearch Dict "ACAD_FILTER"))
            (setq tempDict (dictsearch (cdr (assoc -1 tempDict)) "SPATIAL"))
        )
        (cons '(0 . "SPATIAL_FILTER") (member (assoc 100 tempDict) tempDict))
    )
)
(defun SetSpatialFilter (ename fltData / Data Dict tempDict tempList)
    ; Set the xclip boundry
   
    (if
        (and
            (setq Data (entget ename))
            (setq Dict
                (if (setq tempList (assoc 360 Data))
                    (cdr tempList)
                    (entmakex '((0 . "DICTIONARY") (100 . "AcDbDictionary")))
                )
            )
            (setq tempDict
                (if (setq tempList (dictsearch Dict "ACAD_FILTER"))
                    (cdr (assoc -1 tempList))
                    (dictadd Dict "ACAD_FILTER" (entmakex '((0 . "DICTIONARY") (100 . "AcDbDictionary"))))
                )
            )
        )
        (progn
            (dictremove tempDict "SPATIAL")
            (dictadd tempDict "SPATIAL" (entmakex fltData))
            (entmod
                (if (setq tempList (assoc 360 Data))
                    (subst (cons 360 Dict) tempList Data)
                    (progn
                        (setq tempList (member (assoc 5 Data) (reverse Data)))
                        (append
                            (reverse tempList)
                            (append
                                (list
                                    '(102 . "{ACAD_XDICTIONARY")
                                    (cons 360 Dict)
                                    '(102 . "}")
                                )
                                (member (assoc 5 Data) Data)
                            )
                        )
                    )
                )
            )
        )
    )
)
(defun GetCurrentXrefPath (doc fileName / FileDep cnt tempFd)
   
    (setq FileDep (vla-get-FileDependencies doc))
    (setq cnt 1)
    (while (<= cnt (vla-get-Count FileDep))
        (if
            (and
                (setq tempFd (vla-Item FileDep cnt))
                (= (vla-get-Feature tempFd) "Acad:XRef")
                (= (vla-get-FileName tempFd) fileName)
            )
            (setq cnt (1+ (vla-get-Count FileDep)))
            (setq cnt (1+ cnt)
                tempFd nil
            )
        )
    )
    (if tempFd
        (vla-get-FullFileName tempFd)
    )
)
(defun XrefType (doc xrObj bOverlay / tempEnt tempData InsList XrName XrPath tempXrObj tempXrEnt tempList BlkCol NewXrObj DidSwitch)
   
    (if
        (and
            (setq tempEnt (vlax-vla-object->ename xrObj))
            (setq tempData (entget tempEnt))
            (setq InsList (member (assoc 331 tempData) tempData))
            (setq InsList (cdr (member '(102 . "}") (reverse InsList))))
            (setq tempData (entget (cdr (assoc 360 tempData))))
            (setq XrName (cdr (assoc 2 tempData)))
            (setq XrPath (cdr (assoc 1 tempData)))
            (or
                (findfile Xrpath)
                (setq XrPath (GetCurrentXrefPath doc (strcat (vl-filename-base XrPath) (vl-filename-extension XrPath))))
            )
        )
        (progn
            (foreach i InsList
                (setq tempData (entget (cdr i)))
                (setq tempXrObj
                    (vlax-invoke
                        (vlax-ename->vla-object (cdr (assoc 330 tempData)))
                        'AttachExternalReference
                        XrPath
                        "TempXref"
                        (trans (cdr (assoc 10 tempData)) (cdr (assoc 210 tempData)) 0)
                        (cdr (assoc 41 tempData))
                        (cdr (assoc 42 tempData))
                        (cdr (assoc 43 tempData))
                        (cdr (assoc 50 tempData))
                        bOverLay
                    )
                )
                (vla-put-Layer tempXrObj (cdr (assoc 8 tempData)))
                (vlax-put tempXrObj 'Normal (cdr (assoc 210 tempData)))
                (setq tempXrEnt (vlax-vla-object->ename tempXrObj))
                (if (setq tempList (GetSpatialFilter (cdr i)))
                    (SetSpatialFilter tempXrEnt tempList)
                )
                (if (not BlkCol)
                    (setq BlkCol (vla-get-Blocks doc))
                )
                (entdel (cdr i))
            )
            (vla-Detach xrObj)
            (setq NewXrObj (vla-Item BlkCol "TempXref"))
            (vla-put-Name NewXrObj XrName)
            (setq DidSwitch T)
        )
    )
    DidSwitch
)
Calling commands.
Code: [Select]
(defun c:ToggleXrefs (/ ActDoc Sel EntData BlkCol XrName BlkDef)
   
    (setq ActDoc (vla-get-ActiveDocument (vlax-get-Acad-Object)))
    (vla-EndUndoMark ActDoc)
    (vla-StartUndoMark ActDoc)
    (if
        (and
            (setq Sel (entsel "\n Select xref to toggle between overlay and attach: "))
            (setq EntData (entget (car Sel)))
            (= (cdr (assoc 0 EntData)) "INSERT")
            (setq BlkCol (vla-get-Blocks ActDoc))
            (setq XrName (cdr (assoc 2 EntData)))
            (setq EntData (tblsearch "block" XrName))
            (setq BlkDef (vla-Item BlkCol XrName))
            (equal (vla-get-IsXref BlkDef) :vlax-true)
        )
        (if (equal (logand (cdr (assoc 70 EntData)) 8) 8)
            (if (XrefType (vla-get-ActiveDocument (vlax-get-Acad-Object)) BlkDef 0)
                (prompt (strcat "\n Success in making xref: " XrName ", an attached xref."))
            )
            (if (XrefType (vla-get-ActiveDocument (vlax-get-Acad-Object)) BlkDef 1)
                (prompt (strcat "\n Success in making xref: " XrName ", an overlayed xref."))
            )
        )
    )
    (vla-EndUndoMark ActDoc)
    (princ)
)
(defun c:MakeAttach (/ ActDoc Sel EntData BlkCol XrName BlkDef)
   
    (setq ActDoc (vla-get-ActiveDocument (vlax-get-Acad-Object)))
    (vla-EndUndoMark ActDoc)
    (vla-StartUndoMark ActDoc)
    (if
        (and
            (setq Sel (entsel "\n Select xref to toggle between overlay and attach: "))
            (setq EntData (entget (car Sel)))
            (= (cdr (assoc 0 EntData)) "INSERT")
            (setq BlkCol (vla-get-Blocks ActDoc))
            (setq XrName (cdr (assoc 2 EntData)))
            (setq EntData (tblsearch "block" XrName))
            (setq BlkDef (vla-Item BlkCol XrName))
            (equal (vla-get-IsXref BlkDef) :vlax-true)
            ;(MakeAttach (vla-get-ActiveDocument (vlax-get-Acad-Object)) BlkDef)
            (XrefType (vla-get-ActiveDocument (vlax-get-Acad-Object)) BlkDef 0)
        )
        (prompt (strcat "\n Success in making xref: " XrName ", an attached xref."))
    )
    (vla-EndUndoMark ActDoc)
    (princ)
)
(defun c:MakeOverlay (/ ActDoc Sel EntData BlkCol XrName BlkDef)
   
    (setq ActDoc (vla-get-ActiveDocument (vlax-get-Acad-Object)))
    (vla-EndUndoMark ActDoc)
    (vla-StartUndoMark ActDoc)
    (if
        (and
            (setq Sel (entsel "\n Select xref to toggle between overlay and attach: "))
            (setq EntData (entget (car Sel)))
            (= (cdr (assoc 0 EntData)) "INSERT")
            (setq BlkCol (vla-get-Blocks ActDoc))
            (setq XrName (cdr (assoc 2 EntData)))
            (setq EntData (tblsearch "block" XrName))
            (setq BlkDef (vla-Item BlkCol XrName))
            (equal (vla-get-IsXref BlkDef) :vlax-true)
            ;(MakeOverlay (vla-get-ActiveDocument (vlax-get-Acad-Object)) BlkDef)
            (XrefType (vla-get-ActiveDocument (vlax-get-Acad-Object)) BlkDef 1)
        )
        (prompt (strcat "\n Success in making xref: " XrName ", an overlayed xref."))
    )
    (vla-EndUndoMark ActDoc)
    (princ)
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Andrea

  • Water Moccasin
  • Posts: 2372
Only for information..

you can change Overlay/Attach by doubleClick on it..


Or simply use Reference Manager included with the AutoCAD installation.
to apply modification in batch proccess.
Keep smile...

T.Willey

  • Needs a day job
  • Posts: 5251
True Andrea, but this is coded so that it would work with ObjectDBX.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Joe Burke

  • Guest
Hi Tim,

I've seen this twice.

Command: togglexrefs
 Select xref to toggle between overlay and attach: ; error:
AutoCAD.Application: Invalid argument Xscale in AttachExternalReference

Joe Burke

  • Guest
Tim,

I think the problem is the xref is mirrored so the X scale factor is -1.0.

T.Willey

  • Needs a day job
  • Posts: 5251
Thanks Joe.  I'll look into this tomorrow.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Hi Tim,

I've seen this twice.

Command: togglexrefs
 Select xref to toggle between overlay and attach: ; error:
AutoCAD.Application: Invalid argument Xscale in AttachExternalReference
I got the same error with a mirrored xref.  This has seemed to fix it.  I store the scale values ( per axis ) in a variable.  I then use the absolute value of it when inserting the xref.  I then check the stored scale, and if it is a negative value, I multiply the scale value by a negative 1.  Which seems to work.

Code: [Select]
(defun XrefType (doc xrObj bOverlay / tempEnt tempData InsList XrName XrPath tempXrObj tempXrEnt tempList BlkCol NewXrObj
    DidSwitch tempX tempY tempZ)
   
    (if
        (and
            (setq tempEnt (vlax-vla-object->ename xrObj))
            (setq tempData (entget tempEnt))
            (setq InsList (member (assoc 331 tempData) tempData))
            (setq InsList (cdr (member '(102 . "}") (reverse InsList))))
            (setq tempData (entget (cdr (assoc 360 tempData))))
            (setq XrName (cdr (assoc 2 tempData)))
            (setq XrPath (cdr (assoc 1 tempData)))
            (or
                (findfile Xrpath)
                (setq XrPath (GetCurrentXrefPath doc (strcat (vl-filename-base XrPath) (vl-filename-extension XrPath))))
            )
        )
        (progn
            (foreach i InsList
                (setq tempData (entget (cdr i)))
                (setq tempXrObj
                    (vlax-invoke
                        (vlax-ename->vla-object (cdr (assoc 330 tempData)))
                        'AttachExternalReference
                        XrPath
                        "TempXref"
                        (trans (cdr (assoc 10 tempData)) (cdr (assoc 210 tempData)) 0)
                        (abs (setq tempX (cdr (assoc 41 tempData))))
                        (abs (setq tempY (cdr (assoc 42 tempData))))
                        (abs (setq tempZ (cdr (assoc 43 tempData))))
                        (cdr (assoc 50 tempData))
                        bOverLay
                    )
                )
                (vla-put-Layer tempXrObj (cdr (assoc 8 tempData)))
                (vlax-put tempXrObj 'Normal (cdr (assoc 210 tempData)))
                (setq tempXrEnt (vlax-vla-object->ename tempXrObj))
                (if (setq tempList (GetSpatialFilter (cdr i)))
                    (SetSpatialFilter tempXrEnt tempList)
                )
                (if (not BlkCol)
                    (setq BlkCol (vla-get-Blocks doc))
                )
                (if (< tempX 0.0)
                    (vla-put-XScaleFactor tempXrObj (* -1 (vla-get-XScaleFactor tempXrObj)))
                )
                (if (< tempY 0.0)
                    (vla-put-YScaleFactor tempXrObj (* -1 (vla-get-YScaleFactor tempXrObj)))
                )
                (if (< tempZ 0.0)
                    (vla-put-ZScaleFactor tempXrObj (* -1 (vla-get-ZScaleFactor tempXrObj)))
                )
                (entdel (cdr i))
            )
            (vla-Detach xrObj)
            (setq NewXrObj (vla-Item BlkCol "TempXref"))
            (vla-put-Name NewXrObj XrName)
            (setq DidSwitch T)
        )
    )
    DidSwitch
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Joe Burke

  • Guest
Tim,

That fix looks good.

If you intend to go forward with the code, I think you need to test for nested xrefs. Not doing so will probably cause an error here:

(trans (cdr (assoc 10 tempData)) (cdr (assoc 210 tempData)) 0)

I've been thinking about a function which tests for a nested xref. Here's what I have so far. It seems to work as expected.

 
Code: [Select]
  ;; Arguments: document vla-object and a string representing
  ;; a block name.
  ;; Returns: T if the block is nested, or nil if not.
  ;; Notes: the calling function must check for the validity
  ;; of the block name passed.
  (defun NestedXref (doc blkname / blocks name isnested)
    (setq blkname (strcase blkname)
          blocks (vla-get-Blocks doc)
    )
    (vlax-for x blocks
      (setq name (strcase (vlax-get x 'Name)))
      (if
        (and
          ;; For speed, stop checking if isnested is T.
          (not isnested)
          ;; Filter out model and paper space blocks, xref blocks
          ;; and some others, including the block name argument.
          (not (wcmatch name (strcat "*`**,*|*," blkname)))
          (vlax-property-available-p x 'IsXref)
        )
        (vlax-for i x
          (if
            (and
              (eq "AcDbBlockReference" (vlax-get i 'ObjectName))
              (eq blkname (strcase (vlax-get i 'Name)))
            )                 
            (setq isnested T)
          )
        )
      )
    )
    isnested
  )
 
« Last Edit: October 03, 2008, 09:22:40 AM by Joe Burke »

T.Willey

  • Needs a day job
  • Posts: 5251
That looks like a good method for checking if the xref is nested Joe.  I'll see if I can run some tests on a drawing that has nested xrefs, and see how the routine works.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Joe Burke

  • Guest
Hi Tim,

I think the fuction I posted is incomplete. I'm working on a new version which I'll post when I have time to do more testing.

Incomplete in the sense it only tests the bocks collection to see if the block name passed is contained in some other xref block. But that does not tell the whole story. For instance, assume file A is overlay xrefed to file C. Then file B is xrefed to file C and file A is xref attached to file B. The result in file C is file A is treated as nested, even though it is listed as an overlay in the External References window.

Joe

Joe Burke

  • Guest
Tim,

Switching gears after thinking about it some more. Here's a simple function I've used in other modify xref routines. It has worked well. I'm not sure whether it applies to what you are doing.

Code: [Select]
  ;; Argument: an xref block definition vla-object.
  ;; Returns: T if the xref is nested, otherwise nil.
  ;; Based on code by Stephan Koster in a program named XrefTree.
  ;; Jason Piercey pointed out a known "flaw". Assume file A is first
  ;; xrefed to file C either as an overlay or attached. File A is also
  ;; xref attached to file B. If file B is referenced to file C, file A
  ;; becomes a nested xref in file C, though it was not originally so.
  ;; In that case the code will not detect file A as nested. It will
  ;; return nil when the block definition of file A is passed and file
  ;; C is the active file. This may be considered a feature rather than
  ;; a flaw depending on what the calling function intends to do with
  ;; the return value and the xref in question. For instance, though ACAD
  ;; will not allow the user to change the path or name of file A in
  ;; file C, these things can be changed with code.
  (defun NestedXref (blkdef / elst)
    (setq elst (entget (vlax-vla-object->ename blkdef)))
    (or
      (not (vl-position '(102 . "{BLKREFS") elst))
      (and
        (vl-position '(102 . "{BLKREFS") elst)
        (not (cdr (assoc 331 elst)))
      )
    )
  ) ;end

T.Willey

  • Needs a day job
  • Posts: 5251
Joe,

  Sorry I haven't posted on this subject; I get busy, and forget.   :-)

  I came to the same idea as your second post.  When I ran some test trying to change all the xrefs in a drawing ( when some were nested ), the code wouldn't run on the nested ones because they didn't have the 'blkrefs' section in the block table record entity data.  So I came to the conclusion that my code wouldn't work on nested xrefs, because they don't know where they are inserted, and the one of the tests I do.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Joe Burke

  • Guest
Hi Tim,

Just curious, are you still working the idea?

T.Willey

  • Needs a day job
  • Posts: 5251
Hi Tim,

Just curious, are you still working the idea?
Joe,

As far as I'm thinking now, it is as done as it will be.  It works to switch the xref types as is, and I couldn't get it to work with ObjectDBX, so I stopped on that.  I was able to attach the new xref, and delete the old ones ( the inserted ones, and rename them ), but I couldn't detach them, and when I used the code to get the xclip boundary, I would have to recover the drawings instead of opening.

If you think there is more that could be done to the code, then I'm willing to do a collaboration, but for my purpose; it is finished.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Joe Burke

  • Guest
Tim,

I need to study your last code post and think about the general goals when I have time.