[LISP] How to modify a specific sublist?

[LISP] How to modify a specific sublist?

iBlachu
Advocate Advocate
1,274 Views
15 Replies
Message 1 of 16

[LISP] How to modify a specific sublist?

iBlachu
Advocate
Advocate

In the example below, we have as many as 7 occurrences of sublist No. 42 with different values. How to modify for example 3 sublist with number 42?

 

((-1 . <Nazwa elementu: -15f550>) (0 . "LWPOLYLINE") (330 . <Nazwa elementu: 
-161308>) (5 . "446") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") 
(100 . "AcDbPolyline") (90 . 7) (70 . 1) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 
10.0 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 100.0 0.0) (40 . 0.0) (41 . 0.0) 
(42 . 0.0) (10 100.0 70.0) (40 . 0.0) (41 . 0.0) (42 . 0.414214) (10 70.0 
100.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 20.0 100.0) (40 . 0.0) (41 . 0.0) 
(42 . 0.414214) (10 0.0 80.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 0.0 10.0) 
(40 . 0.0) (41 . 0.0) (42 . 0.414214) (210 0.0 0.0 1.0))

 

0 Likes
Accepted solutions (1)
1,275 Views
15 Replies
Replies (15)
Message 2 of 16

Kent1Cooper
Consultant
Consultant

Those are the bulge factors [for arc segments when not (42 . 0.0)].  How would the three you want to change be specified?  Would you pick on segments whose bulge factor you want to change?  Or would a routine contain some criteria for finding them, such as a particular current value, or anything other than a particular current value?  And how would the desired new value be specified?

 

If the three that are not 0.0 in your sample are the ones you want to change, and you want to change them to 0.0 [i.e. take out the bulge, and make them line segments], you can do them all at once using PEDIT and the Decurve option.  Or you can do them one at a time by selecting the Polyline, hovering over the midpoint grip of any arc segment until it turns red, and typing C for Convert to Line.  Or a routine could be written to find all 42-code entries that are not 0.0 and replace them.

 

[I notice your list does not include 91-code entries, following the 42-code entries, that are part of lightweight Polyline entity data in newer versions:

((-1 . <Entity name: 1cc216b2880>) (0 . "LWPOLYLINE") (330 . <Entity name: 1cc1b9089f0>) (5 . "6BB0") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbPolyline") (90 . 3) (70 . 129) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 216368.0 380165.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 216367.0 380166.0) (40 . 0.0) (41 . 0.0) (42 . -0.984442) (91 . 0) (10 216369.0 380167.0) (40 . 0.0) (41 . 0.0) (42 . -0.44396) (91 . 0) (210 0.0 0.0 1.0))

If that means you're in an older version, I couldn't say whether the Convert to Line option is available in grip-editing.]

 

If you want to change some but not all of the 0.0 values to something else, I think you would need to pick on the segments you want to change.  A routine could find parameter values at the pick locations to determine which segments to change, and from those find the preceding vertices, and "open up" the list to replace 42-code entries in only the right places.

 

Kent Cooper, AIA
Message 3 of 16

iBlachu
Advocate
Advocate

I just gave an example.

I mean programmatically changing a specific occurrence of list 42 on a principle

 

(setq a (entget (entlast)))
(setq a (subst (cons 42 1) (assoc 42 a) a))
(entmod a)

 

0 Likes
Message 4 of 16

ВeekeeCZ
Consultant
Consultant

The easiest way is to use something that allows you to point to an index. Eg.

(setpropertyvalue (car (entsel)) "Vertices" 2 "Bulge" 0.5)

 

You cannot use ASSOC & SUBST. You can use ENTMOD, but you need to manually count/index to identify the particular vertex number and change that (= manually add a new value).

Message 5 of 16

Kent1Cooper
Consultant
Consultant

@iBlachu wrote:

....

....
(setq a (subst (cons 42 1) (assoc 42 a) a))
....

That will replace the bulge factor for only the first segment of the Polyline.  If that's not always what you want, some means of designating which instance(s) you want to change will be needed.

EDIT:  I am surprised to find that (subst) can replace more than one entry of the same DXF code number all at once, given a specific value [not just (assoc 42) that will do only the first instance].  If 'edata' is the entity data list for a Polyline, this code:

(entmod (subst (cons 42 1) (cons 42 0) edata))

converts the left Polyline in this image to the right one:

Kent1Cooper_0-1672663614347.png

that is, turns all line segments into CCW half-circle arc segments [but leaves any existing arc segments alone].

Kent Cooper, AIA
Message 6 of 16

iBlachu
Advocate
Advocate

Exactly, but the whole problem is how to indicate a specific index?

0 Likes
Message 7 of 16

iBlachu
Advocate
Advocate

OK, but you're looking for a list of 42 with a specific value.
But I want to replace e.g. 3 list 42 and its value is unknown.

0 Likes
Message 8 of 16

iBlachu
Advocate
Advocate

This can be done in a loop counting successive occurrences, but isn't there another faster command?

Perhaps there is some command that allows you to navigate nodes?

0 Likes
Message 9 of 16

ВeekeeCZ
Consultant
Consultant

@iBlachu wrote:

Exactly, but the whole problem is how to indicate a specific index?


 

Gave you an example where the 2 doesn't really mean a date.

0 Likes
Message 10 of 16

iBlachu
Advocate
Advocate

 

You only wrote about the algorithm, and did not provide a specific solution. Obviously, that's how it should be done, but with what command? If there isn't one, I'm left with a loop. 😉

0 Likes
Message 11 of 16

ВeekeeCZ
Consultant
Consultant

I must be missing something... which ACAD version you have?

 

The setpropertyvalue is actual function name, SEE .

Message 12 of 16

iBlachu
Advocate
Advocate

2008 😞
So I probably don't have the setpropertyvalue function 😞

0 Likes
Message 13 of 16

ВeekeeCZ
Consultant
Consultant
Accepted solution

The same functionality has the visuallisp - just need to convert an ename to object.

 

(vla-SetBulge (vlax-ename->vla-object (car (entsel))) 2 0.5)

Message 14 of 16

iBlachu
Advocate
Advocate

Thank you.

0 Likes
Message 15 of 16

Sea-Haven
Mentor
Mentor

Setproperty is not supported in some other CAD like Bricscad.

0 Likes
Message 16 of 16

ВeekeeCZ
Consultant
Consultant

It's not too difficult to write your own function. 

 

Two versions. The first one uses a WHILE, the other uses the MAPCAR.

The MAPCAP is more convenient for the job (= simpler), but probably slightly slower than WHILE. The WHILE approach could be even faster than VL's vla-setbulge func. 

 

(defun :set-nth-code (e c n v / i k)   ; ename code n-th value ; returns ename
  (setq i -1 l (entget e))
  (while (if (and (setq x (car l))
		  (= c (car x))
		  (= n (setq i (1+ i))))
	   (setq k (entmod (append (reverse (cons (cons c v) k)) (cdr l)))
		 l nil)
	   (setq k (cons x k)
		 l (cdr l))))
  (cdar k))

 

(defun :set-nth-code (e c n v / i l)  ; ename code n-th value ; returns ename
  (setq i -1 l (entget e))
  (cdar (entmod (mapcar '(lambda (x) (if (and (= c (car x))
					      (= n (setq i (1+ i))))
				       (cons c v)
				       x))
			l))))

 

 

0 Likes