Add a breakline to an existing surface using LISP

Add a breakline to an existing surface using LISP

blair.nixon
Participant Participant
1,324 Views
13 Replies
Message 1 of 14

Add a breakline to an existing surface using LISP

blair.nixon
Participant
Participant

How would I add a standard breakline (3D polyline) to an existing surface using visual LISP? I would like to use LISP in this case and not .NET.

Thanks in advance.

0 Likes
Accepted solutions (2)
1,325 Views
13 Replies
Replies (13)
Message 2 of 14

hosneyalaa
Advisor
Advisor
0 Likes
Message 3 of 14

blair.nixon
Participant
Participant
I've seen that doc already but am looking for an example, if available?
0 Likes
Message 4 of 14

Jeff_M
Consultant
Consultant
Accepted solution

Here is an example to add a Wall breakline, refer to the help for other types.

(defun c:test_AddWallBreakline  ( / *ACAD* ALGN BLKSOBJ C3D C3DDOC DOC ENT E_TYP OBENT PNTS SPC SRF XSTTY)  
  (vl-load-com)
  (defun makevariant (vtype listvalue / )
    (setq array (vlax-make-variant listvalue))    
    (setq sa (vlax-make-safearray  (vlax-variant-type array) (cons 0 0)))
    (vlax-safearray-fill sa (list array))
    sa
    )
  
  (IF     (OR
	    (setq algn (vlax-ename->vla-object (setq lw(car (entsel "\nSelect Polyline: ")))))
	    (while (not (= (vlax-get-property algn 'ObjectName) "AcDbPolyline"))
	      (setq algn (vlax-ename->vla-object (car (entsel "\nSelect Polyline: "))))
	      )
	    )
    (PROGN
      (setq srf (vlax-ename->vla-object (setq ent (car (entsel "\nSelect Surface: ")))))
      (while (not (= (vlax-get-property srf 'ObjectName) "AeccDbSurfaceTin"))
	(setq srf (vlax-ename->vla-object (car (entsel "\nEntity must be C3D Surface. Try again: "))))
	)
      (setq breaks (vlax-get srf 'Breaklines))
      ;;http://docs.autodesk.com/CIV3D/2012/ENU/API_Reference_Guide/com/AeccXLandLib__IAeccSurfaceBreaklines__AddWallBreakline@[in]_VARIANT@[in]_BSTR@[in]_double@[in]_VARIANT@[in]_VARIANT@[out,_retval]_IAeccSurfaceBreakline___.htm
      (vlax-invoke-method
	breaks
	'AddWallBreakline
	(makevariant nil algn)
	(vlax-get-property algn 'HANDLE)
	0.1
	(makevariant vlax-vbdouble  1.0) ;;LEVEL
	(makevariant vlax-vbboolean 1) ;;LEVEL
	)
      )
    )
  (princ)
  )
Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 5 of 14

blair.nixon
Participant
Participant
Accepted solution

That was exactly what I needed!

I was missing/not understanding how to select a polyline and turn it into a variant.

Thank you so much!

0 Likes
Message 6 of 14

hosneyalaa
Advisor
Advisor

HI @Jeff_M 

THANT YOU FOR  an example to add a Wall breakline

But
When I tried it it didn't work An error appeared with me

can you take a look

Command: TEST_ADDWALLBREAKLINE
Select Polyline:
Select Surface: ; error: Automation Error. Description was not provided.

 

Q.gif

0 Likes
Message 7 of 14

Jeff_M
Consultant
Consultant

@hosneyalaa yes, I am seeing the same thing. This is something I wrote years ago and I did not test it prior to posting yesterday. It's been long enough ago that I don't recall if it ever worked. I've just tried a number of things to get it working, none have been successful. When I get some more time I will try again.

Jeff_M, also a frequent Swamper
EESignature
Message 8 of 14

blair.nixon
Participant
Participant

I was looking for a standard breakline and not a wall breakline so I revised the code Jeff posted (if this helps at all).
(defun c:AddSurface (/ surfname brkline C3D verstring prodstring datastr surfs tincreationdata srf breaks)
(setq surfname (getstring 1 "\nEnter surface name = "))
(setq brkline (vlax-ename->vla-object (setq lw(car (entsel "\nSelect Polyline: ")))))
(setq C3D (strcat "HKEY_LOCAL_MACHINE\\" (if vlax-user-product-key (vlax-user-product-key) (vlax-product-key)))
C3D (vl-registry-read C3D "Release")
verstring (substr C3D 1 (vl-string-search "." C3D (+ (vl-string-search "." C3D) 1)))
prodstring (strcat "AeccXUiLand.AeccApplication." verstring)
)
(setq datastr (strcat "AeccXLand.AeccTinCreationData." verstring))
(if (and (setq *acad* (vlax-get-acad-object))
(setq C3D (vla-getinterfaceobject *acad* prodstring))
(setq C3Ddoc (vla-get-activedocument C3D))
(setq surfs (vlax-get C3Ddoc 'surfaces))
(setq tincreationdata (vla-getinterfaceobject *acad* datastr))
)
(progn
(vlax-put tincreationdata 'baselayer "0")
(vlax-put tincreationdata 'layer "0")
(vlax-put tincreationdata 'description "Surface Created by LISP")
(vlax-put tincreationdata 'name surfname)
(if (wcmatch (strcase surfname) "*BASE*")
(vlax-put tincreationdata 'style "_No Display")
(vlax-put tincreationdata 'style "Contours and Triangles")
)
(setq srf (vlax-invoke-method surfs 'addtinsurface tincreationdata))
(setq breaks (vlax-get srf 'Breaklines))
(vlax-invoke-method
breaks
'AddStandardBreakline
(makevariant nil brkline)
(vlax-get-property brkline 'HANDLE)
0.1
)
;add boundary
(vlax-invoke (vlax-get srf 'boundaries) 'add brkline "Created by LISP" 4 :vlax-TRUE 0.05)
;rebuild surface
(vlax-invoke-method srf 'rebuild)
)
)
(princ)
)

0 Likes
Message 9 of 14

john.uhden
Mentor
Mentor

@Jeff_M 

Unlike you, who has advanced to higher lever programming languages, I am forever stuck in AutoLisp, mostly resulting from my days of customizing Land Desktop.

But I am proud that I finally included filtering for raw descriptions in the 6th version of my breakline.lsp program for Civil 3D.  You select one or more 2D or LW polylines (which you have already drawn), provide a layer filter and/or description filter and it creates 3D polylines with vertices added between points on curves.  It makes my life so much easier to create separate breaklines for TC vs. G (or as they use here, BC) when they are right next to one another.  I should probably shrink it by removing all the LDT specific code, but I think maybe if it works, don't fix it.

John F. Uhden

0 Likes
Message 10 of 14

artirtas9100
Explorer
Explorer

Hi all,

I would like to add a selection set of polylines (i've hundreds of them...) per layer as one breakline entry in the Surface Definition/Breaklines.
How do i do that?

I have this so far (changed from the code by blair.nixon):

(setq algnset (ssget "_X" '((0 . "POLYLINE") (8 . "Layername-10") ))) ;; select alle poly-objects on a layer

(setq newset (LM:ss->vla algnset)) ;; convert to VLA objects, thank you Lee Mac

(setq breaks (vlax-get srf 'Breaklines))
(vlax-invoke-method
breaks
'AddStandardBreakline
(makevariant nil newset) ;; to be replaced with a variant of the selection list... but how to do it?
"BL-Layername-10 (added via lisp)"
0.1
)

But I get this error:
error: lisp value has no coercion to VARIANT with this type: (#<VLA-OBJECT IAcad3DPolyline 0000028b11cb0da8> #<VLA-OBJECT IAcadLWPolyline 0000028b54b185e8>
(the same error when you just use newset with makevariant function)

In Civil3D's GUI (2022) you can do this of course but would like to automate it with lisp.


Can somebody shine a light on this?
Thanks in advance!

0 Likes
Message 11 of 14

hosneyalaa
Advisor
Advisor

@artirtas9100  

Can you attached example drawing for testing 

0 Likes
Message 12 of 14

artirtas9100
Explorer
Explorer

Very basic dwg for testing (not a production dwg with hundreds of poly's...)

0 Likes
Message 13 of 14

Jeff_M
Consultant
Consultant

@artirtas9100 here is a lisp that asks you to select the surface then select a polyline on the layer containing polylines. It will then get all polylines on that layer and add them as a single breakline set to the selected surface.

 

(defun c:AddBreaklines2Surface (/ brkline brklines srf breaks ss->array)
  ;; the following function from the AutoCAD Expert's Visual Lisp book
  ;; by Reinaldo N. Togores
  ;; http://lispexpert.blogspot.com/p/blog-page_94.html
  (defun ss->array (sel-set / index array)
    (setq index	0
	  array	(vlax-make-safearray
		  vlax-vbObject
		  (cons 0 (1- (sslength sel-set)))
		)
    )
    (repeat (sslength sel-set)
      (vlax-safearray-put-element
	array
	index
	(vlax-ename->vla-object (ssname sel-set index))
      )
      (setq index (1+ index))
    )
    (vlax-make-variant array)
  )

  (setq	srf (vlax-ename->vla-object
	      (ssname (ssget "_:S+." '((0 . "AECC_TIN_SURFACE"))) 0)
	    )
  )
  (setq	brkline	 (vlax-ename->vla-object
		   (setq lw
			  (car (entsel
				 "\nSelect Polyline on layer with breaklines: "
			       )
			  )
		   )
		 )
	brklines (ss->array (ssget "X"
				   (list '(0 . "*POLYLINE*")
					 (cons 8 (vla-get-layer brkline))
				   )
			    )
		 )
  )
  (setq breaks (vlax-get srf 'Breaklines))
  (vlax-invoke-method
    breaks 'AddStandardBreakline brklines (strcat "added from layer: " (vla-get-layer brkline))  0.1)
					;rebuild surface
  (vlax-invoke-method srf 'rebuild)

  (princ)
)

 

 

Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 14 of 14

artirtas9100
Explorer
Explorer
Jeff,
that ss->array function is a gem... This works great! I would never have found this.
Hopefully I've now the necessary stuff to do something similar with points.
Many thanks for your efforts (and the entire lisp)!
0 Likes