Xref clip alert

Xref clip alert

kameron1967
Collaborator Collaborator
11,400 Views
20 Replies
Message 1 of 21

Xref clip alert

kameron1967
Collaborator
Collaborator

Hi guys,

 

I wonder if you cou ld help me with a lisp routine.  I wanted to go into any drawing and if an xref clip exists (no specified name), it creates a red polyline boundary (possibly from an xclip generate polyline command itself) and alert that there exists an xref clip. Otherwise, it it says, "no xref clip(s) found".  Thanks in advance.

0 Likes
Accepted solutions (2)
11,401 Views
20 Replies
Replies (20)
Message 2 of 21

3wood
Advisor
Advisor

Why you need this alert?

0 Likes
Message 3 of 21

kameron1967
Collaborator
Collaborator
It’s so that I would know if a problem will arise when I bind an xclipped drawing, because once you bind it, every part of that drawing will come in. Hope that helps.
0 Likes
Message 4 of 21

Kent1Cooper
Consultant
Consultant

Quickie beginning of an investigation into where that information is held:

 

What Xclipped Xref [which is (entlast) here] has in entity data that it doesn't have before Xclip [rectangular clip]:
(102 . "{ACAD_XDICTIONARY") (360 . <Entity name: 7ed5ac60>) (102 . "}")


But that much remains in entity data after Deleting the Xclipping from it.

 

What the 360 entry contains with Xclip in effect --
Command: (ENTGET (CDR (ASSOC 360 (ENTGET (ENTLAST)))))

returns:
((-1 . <Entity name: 7ed5ac60>) (0 . "DICTIONARY") (330 . <Entity name: 7ed5ac58>) (5 . "29C") (100 . "AcDbDictionary") (280 . 1) (281 . 1) (3 . "ACAD_FILTER") (360 . <Entity name: 7ed5ac68>))

 

and after Xclipping is Deleted:
((-1 . <Entity name: 7ed5ac60>) (0 . "DICTIONARY") (330 . <Entity name: 7ed5ac58>) (5 . "29C") (100 . "AcDbDictionary") (280 . 1) (281 . 1))

 

It's lost the latter parts.  So at that level, if there's a 360 entry, there seems to be an Xclip in effect.

 

Two more levels down in 360 entries with Xclip in effect:
Command: (entget (cdr (assoc 360 (entget (cdr (assoc 360 (entget (cdr (assoc 360 (entget (entlast)))))))))))

returns:
((-1 . <Entity name: 7ed5ac70>) (0 . "SPATIAL_FILTER") (5 . "29E") (102 . "{ACAD_REACTORS") (330 . <Entity name: 7ed5ac68>) (102 . "}") (330 . <Entity name: 7ed5ac68>) (100 . "AcDbFilter") (100 . "AcDbSpatialFilter") (70 . 2)
(10 37.0 8.5 0.0) (10 40.5 19.0 0.0) ;;;;; <-- corners of rectangular clip
(210 0.0 0.0 1.0) (11 0.0 0.0 0.0) (71 . 1) (72 . 0) (73 . 0) (40 . 1.0) (40 . 0.0) (40 . 0.0) (40 . 0.0) (40 . 0.0) (40 . 1.0) (40 . 0.0) (40 . 0.0) (40 . 0.0) (40 . 0.0) (40 . 1.0) (40 . 0.0) (40 . 1.0) (40 . 0.0) (40 . 0.0) (40 . 0.0) (40 . 0.0) (40 . 1.0) (40 . 0.0) (40 . 0.0) (40 . 0.0) (40 . 0.0) (40 . 1.0) (40 . 0.0))

Those could be used in a RECTANGLE command to draw the Xclip boundary.  I imagine the boundary of a non-rectangular clip would be contained similarly, but haven't dug into that yet.

Kent Cooper, AIA
Message 5 of 21

kameron1967
Collaborator
Collaborator
Kent, similar to checking for a block (although I'm used to seeing the block name being specified, is there a quick way of checking if an xrefclip exist? I'm not following. Thanks.
0 Likes
Message 6 of 21

Kent1Cooper
Consultant
Consultant

@kameron1967 wrote:
Kent, similar to checking for a block (although I'm used to seeing the block name being specified, is there a quick way of checking if an xrefclip exist? I'm not following. Thanks.

An Xrefclip is not an object/entity that can be checked for, but a characteristic applied to an Xref object/entity [which in itself is something that you don't check for directly, but you look at INSERT objects and check whether they are Xrefs rather than just Blocks or WMFs].  I think you could check initially for INSERT objects that have a Dictionary element attached that holds the information about an Xrefclip:

 

(ssget "_X" '((0 . "INSERT") (102 . "{ACAD_XDICTIONARY")))

 

That should find any Xclipped Xref(s), but since Xclipping is not the only thing a dictionary element can contain, it might also find some Blocks that are not Xrefs, and/or some Xrefs that are not clipped.  So you would need to go through whatever that finds, and dig deeper into the information about each, it seems into nested (assoc 360) entries as in my earlier Reply.  I'm not sure at what level you could determine whether an Xref is clipped, in order to know whether to dig deeper to get the clipping boundary, but I may later try setting up a situation and experimenting with it.  The DXF Reference would likely also provide some further direction.

Kent Cooper, AIA
0 Likes
Message 7 of 21

Anonymous
Not applicable

kameron,

 

With help of Lee Mac codes, I made something quick.

As Kent is saying you will need to go a lot more deeper to search for xrefs, but this code might be helpful for you.

It will select all blocks which are inserted in the drawing, and check if block is a xref.

It is not going to search deep into the block, or to search for xclipped xrefs.

 

(defun c:test ( /  ss xrefss x  )
  (setq ss (ssget "_X" '((0 . "INSERT"))))
  (setq xrefss (ssadd))
  (while (setq x (ssname ss 0))
    (if  (eq (vla-get-isxref
	      (vla-item	(vla-get-blocks (LM:acdoc))
			(LM:blockname (vlax-ename->vla-object x))
	      )
	    )
	    :vlax-true
	)
      (ssadd x xrefss)
	  )
      (ssdel x ss)
      )
  (if (setq ename (ssname xrefss 0))
    (while (setq ename (ssname xrefss 0)) 	   
        (setq b (LM:ssboundingbox ename))
        
        (entmake
            (append
               '(
                    (000 . "LWPOLYLINE")
                    (100 . "AcDbEntity")
                    (100 . "AcDbPolyline")
                    (090 . 4)
                    (070 . 1)
                )
                (mapcar '(lambda ( x ) (cons 10 (mapcar '(lambda ( y ) ((eval y) b)) x)))
                   '(
                        (caar   cadar)
                        (caadr  cadar)
                        (caadr cadadr)
                        (caar  cadadr)
                    )
                )
            )
        )
      (ssdel ename xrefss)
      );end while
    (alert "\Function didn't find xref in drawing!")
    )
    (princ)
)
(vl-load-com)


;; Selection Set Bounding Box  -  Lee Mac
;; Returns a list of the lower-left and upper-right WCS coordinates of a
;; rectangular frame bounding all objects in a supplied selection set.
;; s - [sel] Selection set for which to return bounding box

(defun LM:ssboundingbox ( ename / a b i m n o )
    ;(repeat (setq i (sslength s));-edited
        (if
            (and
;(setq o (vlax-ename->vla-object (ssname s (setq i (1- i)))));-edited (setq o (vlax-ename->vla-object ename));-edited (vlax-method-applicable-p o 'getboundingbox) (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-getboundingbox (list o 'a 'b)))) ) (setq m (cons (vlax-safearray->list a) m) n (cons (vlax-safearray->list b) n) ) ) ;);-edited (if (and m n) (mapcar '(lambda ( a b ) (apply 'mapcar (cons a b))) '(min max) (list m n)) ) ) ;; Block Name - Lee Mac ;; Returns the true (effective) name of a supplied block reference (defun LM:blockname (obj) (if (vlax-property-available-p obj 'effectivename) (defun LM:blockname (obj) (vla-get-effectivename obj)) (defun LM:blockname (obj) (vla-get-name obj)) ) (LM:blockname obj) ) ;; Active Document - Lee Mac ;; Returns the VLA Active Document Object (defun LM:acdoc nil (eval (list 'defun 'LM:acdoc 'nil (vla-get-activedocument (vlax-get-acad-object)) ) ) (LM:acdoc) )

 Hope this is helpful,

dicra

0 Likes
Message 8 of 21

Kent1Cooper
Consultant
Consultant
Accepted solution

So I discovered something I hadn't known:  I don't know in which release this feature appeared, but in 2015 the Xclip command has an option to generate Polylines around the clipping boundaries of all [and all at once] selected Xrefs that are Xclipped!  The following XClipID command looks for INSERT objects with (assoc 360) entries as candidates, and if it finds any with a nested 360 entry inside the top-level one, it stops checking and just makes red Polylines around the borders of all there are.  NOTE:  I have not yet dug into the question of whether there can be 360 entries in the entity data of Xrefs under any circumstances other than their being [or having been -- see my first Reply] Xclipped, so if there can be, this may mislead.  [Or it may possibly fail since, while the "generate Polyline" option always shows in the prompt, it is ignored if chosen when there are no Xclipped Xrefs among the selection, and it goes back to the prompt instead of ending the command.]  I also wanted to have it make the red Polylines wider, to be more noticeable, but for some reason those that are generated around Xclip boundaries are not affected by the PLINEWID System Variable, but are always of 0 width.  It could be done, but would take some additional shenanigans.  Lightly tested, and it could use the usual enhancements [error handling, command-echo suppression, etc.].  [That's a capital letter I second from the end in the command name, not a lower-case letter l like the third letter, nor a number 1.]

 

(defun C:XClipID (/ ss n xrdata xc cec); = IDentify Xclipped Xrefs [with red Polyline clipping boundaries]
  (if (setq ss (ssget "_X" '((0 . "INSERT"))))
    (progn ; then
      (setq n (sslength ss))
      (while (and (not xc) (> n 0)); haven't found one yet, nor reached end of selection
        (if (assoc 360 (setq xrdata (entget (ssname ss (setq n (1- n)))))); possibly Xclipped Xref
          (setq xc (assoc 360 (entget (cdr (assoc 360 xrdata))))); then --
            ; [nil if none] found nested 360 entry; stop loop
        ); if
      ); while
    ); progn
  ); if
  (if xc
    (progn ; then -- found at least one; add red Polylines to all
      (setq cec (getvar 'cecolor))
      (setvar 'cecolor "red")
      (command "_.xclip" "_all" "" "_polyline")
      (setvar 'cecolor cec); reset
    ); progn
    (alert "No Xclipped Xref found."); else
  ); if
); defun

 

For those with earlier versions without the generate-Polylines option in Xclip, I think it could still be done, but it would be necessary to dig down into the nature of the definition of Polygonal clipping boundaries vs. Rectangular ones, and making the Polyline from that information would need to be done for each clipped Xref separately, rather than collectively.

Kent Cooper, AIA
Message 9 of 21

kameron1967
Collaborator
Collaborator
Thanks, Kent! That's exactly what I was looking for. Thanks for the code as well, Lee. You guys rock! 🙂
0 Likes
Message 10 of 21

kameron1967
Collaborator
Collaborator
dicra,
Hi. Thank you for your version of the routine as well. However, the boundaries that it created are too wide that it's difficult to tell which xref the clip belongs to. When I have a lot of xclipped entities, having be tight around the xref being xclipped is greatly desired. I might use it for when I don't have so many xclips in one drawing. Thanks again! 🙂
0 Likes
Message 11 of 21

kameron1967
Collaborator
Collaborator
This is exactly what I was looking for, Kent. Thanks! 🙂
0 Likes
Message 12 of 21

Kent1Cooper
Consultant
Consultant

@kameron1967 wrote:
This is exactly what I was looking for, Kent. Thanks! 🙂

You're welcome.  I found that the generate-Polyline option is present at least as far back as Acad 2004, though I had never noticed it there before.

 

I figure I will sometimes have a use for the same, so I developed it a little further in the attached XCLIPID.lsp file.  It has error handling, suppresses command echoing, makes the Polylines fatter so they're more noticeable, restricts it to the current space [because XCLIP doesn't like to deal with Xrefs that are elsewhere], and wraps it all in an Undo container so you can undo the whole operation at once.

Kent Cooper, AIA
0 Likes
Message 13 of 21

kameron1967
Collaborator
Collaborator

That's awesome, Kent. Yes, I was looking into how to make the lines thicker. I also had it create a layer called XCLIPBOUNDARY to contain those xclipped lines so they could be frozen at leisure. Also, the alert - "no xclipped xref found" is probably not needed, but I modified it and placed it within the routine so it will alert you if an xclipped xref(s) exist. Other change is the linetype - to phantom.  But great job making it better, Kent! hehe

 

In case anyone else wonder, I've only modified these lines.  Kent provided all the instructions, so it was very easy to modify. Cheers! 🙂

 

(mapcar 'setvar svnames '("blue" 0)); <-- edit "red" if different color desired [in quotes even if numerical]
(COMMAND "-LAYER" "M" "XCLIP_BOUNDARY" "C" "6" "XCLIP_BOUNDARY" "L" "PHANTOM" "" "")
(command "_.xclip" "_all" "" "_polyline")
(alert "Xclipped Xref found! Type REGEN and look for BLUE Phantom lines."); else
(while (setq base (entnext base))
(entmod (append (entget base) (list (cons 43 (/ (getvar 'viewsize) 3000))))); <-- edit 100 for desired width

0 Likes
Message 14 of 21

kameron1967
Collaborator
Collaborator

Kent,

 

The routine works great most of the time, but I get the message saying an xclip exists on a drawing that does not have any xrefs in it.  Can you check into it for me? Also, it tends to pull up a help screen whenever I get into this drawing.  There's something in the routine that's making it do that.  Also, it seems to be stuck in an xclip command whenever I go into a file without any xclip.  I am attaching a file for you to check into.  Thanks, Kent!

0 Likes
Message 15 of 21

Kent1Cooper
Consultant
Consultant
Accepted solution

@kameron1967 wrote:

... I get the message saying an xclip exists on a drawing that does not have any xrefs in it.  ... Also, it tends to pull up a help screen whenever I get into this drawing.  ....


You've run up against what I wondered about in the sentence following "NOTE:" in Post 8.  It appears ordinary Blocks can also have nested (assoc 360) entries, though it would take more research to know what the possibilities are.  The Help thing is probably because something about its finding a Block that it can't get a clipping boundary from results in an Enter being fed into the Command: line somehow.  When that happens first thing, and there's no previous command to recall with it, Help comes up.

 

Try the attached adjusted file, which has an added element to check whether an Insert object is an Xref rather than just a Block:

....

        (if
          (and
            (setq xrdata (entget (ssname ss (setq n (1- n)))))
            (assoc 1 (tblsearch "block" (cdr (assoc 2 xrdata)))); it's an Xref
            (assoc 360 xrdata); possibly Xclipped
          ); and
          (setq xc (assoc 360 (entget (cdr (assoc 360 xrdata))))); then --
            ; [nil if none] found nested 360 entry; stop loop
        ); if

....

 

It worked in a quick test on your sample drawing.  But I don't guarantee that there aren't other circumstances that might similarly fool it.

Kent Cooper, AIA
0 Likes
Message 16 of 21

kameron1967
Collaborator
Collaborator
Yes, that worked, Kent. You're awesome, dude! 🙂
0 Likes
Message 17 of 21

Kent1Cooper
Consultant
Consultant

Here's a slightly revised/improved version.  It ensures that (vl...) functions will be available, and prompts with the command name when loaded.

Kent Cooper, AIA
0 Likes
Message 18 of 21

kameron1967
Collaborator
Collaborator
Thanks again, Kent. I used the new code and it's working without a hitch! lol
0 Likes
Message 19 of 21

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

Here's a slightly revised/improved version.  ....



... and here's another update of XclipID.lsp.  Since ordinary Blocks can also be Xclipped, this does the identifying of both Xrefs and Blocks.  If you want to identify clipping boundaries on only Xrefs, use the earlier version, or follow the instructions in this one's code [the Xref identifier is still there, but commented out, so it can be restored].

Kent Cooper, AIA
0 Likes
Message 20 of 21

kameron1967
Collaborator
Collaborator

Thanks, Kent! You're such a perfectionist! LOL

0 Likes