Section View Surface Display/Plot Order Control / Lisp Command

Section View Surface Display/Plot Order Control / Lisp Command

RDunkley
Advocate Advocate
3,673 Views
17 Replies
Message 1 of 18

Section View Surface Display/Plot Order Control / Lisp Command

RDunkley
Advocate
Advocate

Hi All,

I have found that the Display/Plot order for Section View Surfaces appears to be random. Sometimes the Design surface plots on top of all other linework and others it will sit behind and looks terrible. I know that I can fix this by selecting my Design Surface Section > Select Similar > Display Order> Bring to Front. I would like to make this an automated process but am struggling to get it to work.

I have tested the LayerOrder command with no luck and am also struggling to get any Lisp code to select the surface as they are defined as a 'Section' (Aecc object) but seems to sit as part of a larger group on a layer called 'C-SECTION' with the Design Surface on layer 'C-SECTIONS_Surfaces_Design'.

Ideally some kind of routine would run when the Section Views are regenerated to bring all Design Surface linework (Sections on layer 'C-SECTIONS_Surfaces_Design') to front.

Thanks.

 

Currently using Civil 3D 2024 & AutoCAD 2025
0 Likes
3,674 Views
17 Replies
Replies (17)
Message 2 of 18

RDunkley
Advocate
Advocate

Anyone..? Does anybody else have issues with the Display Order for Section View Surfaces?

Currently using Civil 3D 2024 & AutoCAD 2025
0 Likes
Message 3 of 18

GTVic
Advisor
Advisor

Would this work?

 

Select only:

  • (progn (setq ss11 (ssget "x" '((0 . "AECC_SECTION")))) (sssetfirst nil ss11))

Select and bring to front:

  • (command "_.draworder" (ssget "x" '((0 . "AECC_SECTION"))) "" "_front")

I tested it on the Autodesk sample drawing: Plan Production-Section Sheets-Create.dwg

  • picking on one of the design section surfaces in the section views and then using Select Similar picks 182 entities
  • the above LISP picks 273 which is an additional 91 entities
  • the entities show as "Section" in the properties palette
  • they show as AECC_SECTION in the LIST command

GTVic_0-1714619282300.png

 

0 Likes
Message 4 of 18

Jeff_M
Consultant
Consultant

To add to what @GTVic suggested, include the specific layer for the Design surface:

  • (command "_.draworder" (ssget "x" '((0 . "AECC_SECTION")(8 . "C-SECTIONS_Surfaces_Design"))) "" "_front")
Jeff_M, also a frequent Swamper
EESignature
Message 5 of 18

RDunkley
Advocate
Advocate

Thanks @GTVic & @Jeff_M.

I get an "unknown command for _front" error when I try to include the specific layer filter.  Without this it works ok..?

Currently using Civil 3D 2024 & AutoCAD 2025
0 Likes
Message 6 of 18

Jeff_M
Consultant
Consultant

I used copy-paste on that line of lisp I posted and this is what I got:

Command: _.draworder
Select objects: 30 found
Select objects:
Enter object ordering option [Above objects/Under objects/Front/Back] <Back>: _front
Command:

Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 7 of 18

GTVic
Advisor
Advisor

The LISP is just sample code and not very robust, it will fail if no surfaces are found and then you could get that error.

 

(defun c:sstf ( / ss ft )
  (setq ft '((0 . "AECC_SECTION") (8 . "C-SECTIONS_Surfaces_Design")))
  (if (setq ss (ssget "x" ft))
    (progn (command "_.draworder" ss "" "_front")
           (princ "\nDraw order updated"))
    (princ "\nNo matching surfaces found"))
  (princ))

 

Message 8 of 18

RDunkley
Advocate
Advocate

Hi Jeff, I'm sorry but I couldn't get it to work...

I pasted your code, as described with no luck. Please see attached video to show the error.

Regards.

(view in My Videos)
 

Currently using Civil 3D 2024 & AutoCAD 2025
0 Likes
Message 9 of 18

RDunkley
Advocate
Advocate

Hi @GTVic, Your code is working if I either omit the Layer filter or change the Layer filter to "C.-SECTION" (As shown) as this appears to be the 'Parent' layer for the Section. Unfortunately, This will bring all Sections to the front, I need to select only the Design Surface Section which has a different 'Child' layer... "C-SECTIONS_Surfaces_Design" and it doesn't seem to work for that?

(defun c:sstf ( / ss ft )
  (setq ft '((0 . "AECC_SECTION") (8 . "C-SECTION")))
  (if (setq ss (ssget "x" ft))
    (progn (command "_.draworder" ss "" "_front")
           (princ "\nDraw order updated"))
    (princ "\nNo matching surfaces found"))
  (princ))

 Another possible solution might be to include a check for the Design Section Style "ANZ_Surface Design" in the filter..? However I haven't been able to find a reference on how to filter by AEC Style. 

Regards.
Ross.

Currently using Civil 3D 2024 & AutoCAD 2025
0 Likes
Message 10 of 18

Jeff_M
Consultant
Consultant

@RDunkley so your sections are actually on layer C-SECTIONS not the one being called for in the filter. You had said they are on the layer we used for the filter but that is just the layer specified in the style. The only way to filter based on style would be to open each section in the selectionset and check the style used, creating a new selectionset with only those using the specified style. 

Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 11 of 18

Jeff_M
Consultant
Consultant

@RDunkley here is a lisp that looks in the section styles for any that use the specified layer for the segments (note that it will use the last one found! It could be modified to use all found styles), then gets all the sections and checks each one to see if it is using the style found, if found, those are added to a new ss and that ss is used to set the draw order.

 

(defun c:sectionstofront ( / CIVAPP CIVDOC DISPLAY ENT HAND I LAYER NEWSS SECTION SS STYLE STYLES)
  (setq layer "C-SECTIONS_Surfaces_Design") ;;set the layer to look for here
  
  (defun getaeccApp (module / *acad* C3D) ;; module must be "Land", "Pipe", "Roadway", or "Survey"
  (vl-load-com)
  (if (and (setq *acad* (vlax-get-acad-object))
	   (setq C3D (strcat "HKEY_LOCAL_MACHINE\\"
			     (if vlax-user-product-key
			       (vlax-user-product-key)
			       (vlax-product-key)
			     )
		     )
		 C3D (vl-registry-read C3D "Release")
		 C3D (substr
		       C3D
		       1
		       (vl-string-search
			 "."
			 C3D
			 (+ (vl-string-search "." C3D) 1)
		       )
		     )
		 C3D (vla-getinterfaceobject
		       (vlax-get-acad-object)
		       (strcat "AeccXUi" module ".Aecc" (if (= (strcase module) "LAND") "" module) "Application." C3D)
		     )
	   )
      )
    C3D
  )
)
  (if (setq ss (ssget "X" '((0 . "AECC_SECTION"))))
    (progn
	  (setq civapp (getaeccapp "Land")
		civdoc (vlax-get civapp 'activedocument)
		styles (vlax-get civdoc 'sectionstyles)
		)
      (vlax-for s styles
	(setq display (vlax-get s 'SegmentDisplayStyleSection))
	(if (eq (vlax-get display 'layer) layer)
	  (setq hand (vlax-get s 'handle))
	  )
	)
      (setq newss (ssadd)
	    i -1)
      (while (setq ent (ssname ss (setq i (1+ i))))
	(setq section (vlax-ename->vla-object ent))
	(if (= (vlax-get (vlax-get section 'style) 'handle) hand)
	  (ssadd ent newss)
	  )
	)
      (if (> (sslength newss) 0)
	(progn (command "_.draworder" newss "" "_front")
           (princ "\nDraw order updated"))
	)
      (vlax-release-object civapp)
      )
    )
  (princ)
  )

 

Jeff_M, also a frequent Swamper
EESignature
Message 12 of 18

RDunkley
Advocate
Advocate

Hi @Jeff_M,

Thankyou so much!

Once I realised that I needed to set a Layer Name that is unique to the Section Style I want to bring to the front (to ensure that the Section Style I was using was the only one picked up) it worked great!

 

If you have the time, or patience, I would appreciate it if you were able to show me how the code could be modified to use all found styles with comments? As I think this would be more robust.

 

Additionally, from your understanding, am I right in assuming that Civil 3D has no in-built way to control the display/plot order of these Sections? It seems quite odd.

 

And finally, Ideally this script would run 'automatically' once set up so the user doesn't need to remember to do it. Do you have any suggestions as to how this could be achieved? Ie. Could it be run as part of the Publish command or on Save or something else, even when Section Styles are set? It seems to run quickly so may not be too noticeable if it happens on a semi-regular basis...

Currently using Civil 3D 2024 & AutoCAD 2025
0 Likes
Message 13 of 18

Jeff_M
Consultant
Consultant

@RDunkley Here is a snippet of the code showing the 2 lines of code that need to be changed to get and filter all styles using the layer:

 

  (if (setq ss (ssget "X" '((0 . "AECC_SECTION"))))
    (progn
	  (setq civapp (getaeccapp "Land")
		civdoc (vlax-get civapp 'activedocument)
		styles (vlax-get civdoc 'sectionstyles)
		)
      (vlax-for s styles
	(setq display (vlax-get s 'SegmentDisplayStyleSection))
	(if (eq (vlax-get display 'layer) layer)
	  (setq hand (cons (vlax-get s 'handle) hand));;changed
	  )
	)
      (setq newss (ssadd)
	    i -1)
      (while (setq ent (ssname ss (setq i (1+ i))))
	(setq section (vlax-ename->vla-object ent))
	(if (member (vlax-get (vlax-get section 'style) 'handle) hand);;changed
	  (ssadd ent newss)
	  )
	)

 

 

Correct, no way to set the order directly. 

 

This may be added to a command which replaces the plot or save command. It's been a while since I've used reactors in lisp to automate the update, not sure if command calls can be used in them. Perhaps @hippe013  can chime in on that.

Jeff_M, also a frequent Swamper
EESignature
Message 14 of 18

hippe013
Advisor
Advisor

@Jeff_M Unfortunately the command function is not allowed in a reactor callback function.  Adding the command function to a callback results in AutoCAD rejecting the command. Is there another way to set draworder without using "Command"? 

 

; error: AutoCAD command rejected: "DRAWORDER"

 

0 Likes
Message 15 of 18

Jeff_M
Consultant
Consultant

@hippe013 wrote:

Is there another way to set draworder without using "Command"? 

 


Yes, using Lee Mac's tools would be easiest. Or just creating them as there isn't that much to them.

Jeff_M, also a frequent Swamper
EESignature
Message 16 of 18

GTVic
Advisor
Advisor

Reference to .NET method for modifying draw order:

https://www.keanw.com/2010/10/changing-the-relative-draw-order-of-autocad-objects-based-on-their-lay...

 

Reference to COM method for modifying draw order:

https://forums.autodesk.com/t5/vba/vb-net-draw-hatch-send-to-back-programatically/td-p/6618389

 

The above is just meant for general reference. The command method is not desirable for many reasons including reliability.

0 Likes
Message 17 of 18

hippe013
Advisor
Advisor

@Jeff_M 

Lee's style of writing lisp is so clean and elegant. I am always amazed at his work. 

 

 

***EDIT***

Below is an example of creating an object modified reactor. 

 

(setq reactor (vlr-object-reactor (list watchedObject) '(( :vlr-modified . OnObjectModified))))

(defun OnObjectModified (obj dat1 dat2)
  (princ "\nObject has been modified.")
  )

 

 

0 Likes
Message 18 of 18

hippe013
Advisor
Advisor

I've edited my previous response and code. The object that is being watched cannot be the object that is being modified and I believe that changing the draw order "modifies" the object, but I haven't tested this out. It seems to me that the surface should be the object that is watched for modification and the sections then get modified through the draw order inside the callback function that is triggered by the reactor. My previous code didn't make that distinction very clear. 

 

So, it seems to me that it would work to create an object-modified reactor and apply it to the surface. Then in the callback function get your appropriate sections and change the draw order using the Lee Mac functions that @Jeff_M posted. 

0 Likes