LWPolyline Start & End Point

LWPolyline Start & End Point

11706013
Participant Participant
3,887 Views
14 Replies
Message 1 of 15

LWPolyline Start & End Point

11706013
Participant
Participant

Hi All,

 

Was just wondering if anyone would be able to tell me how to set the start and end points of a LWPOLYLINE, i.e. if the following works for a LINE then how can I update it to be compatible with both entity types? 

 

(vlax-put-property pb 'StartPoint (vlax-3d-point p1)) ; where pb is a vla-object, p1 is a point list.

 

Thanks in advance.

0 Likes
Accepted solutions (1)
3,888 Views
14 Replies
Replies (14)
Message 2 of 15

marko_ribar
Advisor
Advisor

LWPOLYLINE is strictly planar entity, so to set start point via (vlax-3d-point p1) variant won't work and 'StartPoint property of vla-object LWPOLYLINE interface is not available... If you need to change starting point position, you should consider transforming 3D point from 3D space to LWPOLYLINE plane and then use those coordinates to change first DXF GC 10 of entity data of LWPOLYLINE... So I would suggest something like this : (entupd (cdr (assoc -1 (entmod (subst (cons 10 (trans p1 0 lw)) (assoc 10 (entget lw)) (entget lw))))))

Of course "p1" is start point in WCS and "lw" is LWPOLYLINE ename - not vla-object... Variables should be considered without quotes like it's written in syntax (entupd .... )

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 3 of 15

marko_ribar
Advisor
Advisor

Similarily for end point, you can also (entmod) entity data for last vertex... (entupd (cdr (assoc -1 (entmod (subst (cons 10 (trans p2 0 lw)) (assoc 10 (reverse (entget lw))) (entget lw))))))... Note that I deliberately marked (reverse) function as you need first (assoc 10) but from reversed entity data list - meaning association of last GC 10 of normal entity data list... That is all, you could also alter coordinates property if you strictly wish to go via Visual LISP approach, but this is far more simple and it gets you to desired result in IMHO very elegant way...

Marko Ribar, d.i.a. (graduated engineer of architecture)
0 Likes
Message 4 of 15

dbhunia
Advisor
Advisor

@11706013 wrote:

Hi All,

 

Was just wondering if anyone would be able to tell me how to set the start and end points of a LWPOLYLINE, i.e. if the following works for a LINE then how can I update it to be compatible with both entity types? 

 

(vlax-put-property pb 'StartPoint (vlax-3d-point p1)) ; where pb is a vla-object, p1 is a point list.

 

Thanks in advance.


 

If you are handling with "LWPOLYLINE" or "AcDbPolyline", then you can recreate it by considering the Start/End/any Point ...... like this......

 

(defun C:LWPoly ( / LWP LWP_Ent LWP_SP LWP_EP LWP_cor PN PC cmd)

(if (and (= "LWPOLYLINE" (cdr (assoc 0 (setq LWP (entget (setq LWP_Ent (car(entsel))))))))
		 (setq LWP_SP (getpoint "\nPick/Enter Point Start : "))
		 (setq LWP_EP (getpoint "\nPick/Enter Point End : "))
	)
	(progn
		(foreach val LWP(if (eq 10 (car val)) (setq LWP_cor (cons (cdr val) LWP_cor))))
		(setq PN (length LWP_cor) PC 0)
		(setq cmd (getvar 'cmdecho))
		(setvar 'cmdecho 0)
		(command "_.pline")
		(repeat PN 
			(setq PC (+ 1 PC))
			(setq point (nth (1- PC) LWP_cor))
			(if (= PN PC)(setq point LWP_SP));Start Point
			(if (= 1 PC)(setq point LWP_EP));End Point
			(command "_none" point)
		)
		(while (/= (getvar "cmdactive") 0)(command ""))
		(entdel LWP_Ent)
		(setvar 'cmdecho cmd)
	)
)
(princ)
)

Then go for MATCHPROP/CHPROP like THIS

 

 


Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 5 of 15

ВeekeeCZ
Consultant
Consultant

HERE is interesting thread about how to work with lwpolyline's coordinates in same fashion as your example.

Since the properties are different

Line: Start+EndPoint  vs  Lwpolyline: Coordinates or Coordinate,

you cannot use just one of them to cover both entity types.

0 Likes
Message 6 of 15

Kent1Cooper
Consultant
Consultant

@11706013 wrote:

.... how to set the start and end points of a LWPOLYLINE, i.e. if the following works for a LINE then how can I update it to be compatible with both entity types? 

....


 

Is it possible that you want to apply such a thing only to a single-line-segment zero-width  LWPolyline?  That would be "equivalent" to a Line except for entity type, and I'm having a hard time picturing a situation in which one would want to change the start- and end-points of a multi -segment Polyline but leave all the intermediate vertices where they are.  [I'd be interested in the circumstances if that's what you're after.]

 

If the answer that that question is Yes, consider just EXPLODE-ing the Polyline, and applying your code to the resulting Line.  You can then PEDIT it back to a Polyline if there's any reason to.

Kent Cooper, AIA
0 Likes
Message 7 of 15

11706013
Participant
Participant

Thanks everyone for your replies,

 

I came up with the following function to apply to either ent type using the link attached in BeekeeCZ's post, not sure how robust it is but it appears to work okay for now:

 

 

(defun _modendpoint ( vla pt end / typ i coords subst-i 2d-coord->pt-lst )

	;; Two following subfunctions by Gilles Chanteau
	;; Subst-i
	;; Replaces the item at specified index by a new one
	(defun subst-i (new ind lst)
		(if (or (zerop ind) (null lst))
			(cons new (cdr lst))
			(cons (car lst) (subst-i new (1- ind) (cdr lst)))
	)	)
	;;; 2d-coord->pt-lst
	;; Converts a 2d coordinates flat list into a 2d point list
	;;; (2d-coord->pt-lst '(1.0 2.0 3.0 4.0)) -> ((1.0 2.0) (3.0 4.0))
	(defun 2d-coord->pt-lst (lst)
		(if lst
			(cons (list (car lst) (cadr lst))
				(2d-coord->pt-lst (cddr lst))
	)	)	)

	(setq typ (vla-get-objectname vla))
	(if end 
		(cond	(	(eq typ "AcDbPolyline")
				(setq	i (1- (vl-list-length (setq coords (2d-coord->pt-lst (vlax-get vla 'coordinates)))))
					coords (subst-i pt i coords)
				)
				(vlax-put vla 'coordinates (apply 'append coords))
			)
			(	(eq typ "AcDbLine")
				(vlax-put-property vla 'EndPoint (vlax-3d-point pt))
		)	)
		(cond	(	(eq typ "AcDbPolyline")
				(setq coords (subst-i pt 0 (2d-coord->pt-lst (vlax-get vla 'coordinates))))
				(vlax-put vla 'coordinates (apply 'append coords))
			)
			(	(eq typ "AcDbLine")
				(vlax-put-property vla 'StartPoint (vlax-3d-point pt))
	)	)	)
	(princ)
)

 

0 Likes
Message 8 of 15

11706013
Participant
Participant

@Kent1Cooper wrote:

Is it possible that you want to apply such a thing only to a single-line-segment zero-width  LWPolyline? 


Some of the polylines I'm dealing with will be multi-segmented and have a width as the code is being designed for hydraulic drafting and some services may be shown thicker than others. We mainly deal with just lines but I was aiming to make my code more widely applicable.

 

 

0 Likes
Message 9 of 15

Kent1Cooper
Consultant
Consultant

@11706013 wrote:....

Some of the polylines I'm dealing with will be multi-segmented and have a width as the code is being designed for hydraulic drafting and some services may be shown thicker than others. We mainly deal with just lines but I was aiming to make my code more widely applicable.



Maybe this is not a viable suggestion, if [for example] your start/end points are coming from preceding code rather than User selection, but just in case....

 

So in any routine for this kind of thing, you need to select the Line/Polyline, and you need to have the new locations for the ends established.  If those are by User selection, how 'bout, instead, just grip-editing it?  No code required, no command [custom or otherwise] to invoke, works the same for either entity type, and the only additional step is, after picking the Line/Polyline, you need to pick on the grip at each end before picking the new location for it.  And it lets you change only one  end, if that's sometimes appropriate, without running into errors.

Kent Cooper, AIA
0 Likes
Message 10 of 15

ronjonp
Advisor
Advisor
Accepted solution

Here is another way to do it ( only for lines and lwpolylines ).

(defun foo (e p1 p2 / ep sp)
  ;; RJP » 2019-07-08
  (if e
    (progn (setq sp (vlax-curve-getstartpoint e))
	   (setq ep (vlax-curve-getendpoint e))
	   (cond ((= "LWPOLYLINE" (cdr (assoc 0 (entget e))))
		  (setq sp (mapcar '+ sp '(0 0)))
		  (setq ep (mapcar '+ ep '(0 0)))
		 )
	   )
	   (entmod (mapcar '(lambda (x)
			      (cond ((equal sp (cdr x) 1e-8) (cons (car x) p1))
				    ((equal ep (cdr x) 1e-8) (cons (car x) p2))
				    (x)
			      )
			    )
			   (entget e)
		   )
	   )
    )
  )
)
(foo (car (entsel)) (getpoint) (getpoint))
0 Likes
Message 11 of 15

11706013
Participant
Participant

rperez,

 

Thank you I like how concise your code is and doesn't have a need for multiple ifs & conds like mine.

I also didn't realise the "vlax-curve-" functions work on enames so that's good to know. 

 

Could you please explain why the (x) is located within the (cond) function as it is?

I haven't seen cond used like that before.

	   (entmod (mapcar '(lambda (x)
			      (cond ((equal sp (cdr x) 1e-8) (cons (car x) p1))
				    ((equal ep (cdr x) 1e-8) (cons (car x) p2))
				    (x) ; this x
			      )
			    )
			   (entget e)
		   )
	   )

 

0 Likes
Message 12 of 15

11706013
Participant
Participant

 


@Kent1Cooper wrote:

Maybe this is not a viable suggestion, if [for example] your start/end points are coming from preceding code rather than User selection, but just in case....

Kent,

The inputs do come from preceding code. The code works by allowing the user to select a "trunk" line using (entsel) and then selecting the lines to connect to the trunk line via (ssget).

The new locations for the end points are found using a combination of Lee Mac's LM:intersections subfunction and the polar function. 

If you'd like I can upload the full code so you can get a greater understanding of what the point of the code is. It currently works completely for line objects I just haven't gotten around to fully adapting it for lwpolylines. 

 

0 Likes
Message 13 of 15

ВeekeeCZ
Consultant
Consultant

@11706013 wrote:

...

Could you please explain why the (x) is located within the (cond) function as it is?

I haven't seen cond used like that before.

	   (entmod (mapcar '(lambda (x)
			      (cond ((equal sp (cdr x) 1e-8) (cons (car x) p1))
				    ((equal ep (cdr x) 1e-8) (cons (car x) p2))
				    (x) ; this x
			      )
			    )
			   (entget e)
		   )
	   )

 


 

It's also very common when you have some user input with a default value:

  (or *val*
      (setq *val* 20.))
  
  (setq *val* (cond ((getdist (strcat "\nSet distance <" (rtos *val* 2 2)">: ")))
                    (*val*)))

See help HERE for an explanation. Especially this part:

Return Values: The value of the last expression in the sublist. If there is only one expression in the sublist (that is, if result is missing), the value of the test expression is returned. If no arguments are supplied, cond returns nil.

 

See the word value, that's the nicest part. It does not return just True but its Value! Compare this behavior to the OR and AND functions ... those return just True. 

0 Likes
Message 14 of 15

ronjonp
Advisor
Advisor

@11706013 wrote:

rperez,

 

Thank you I like how concise your code is and doesn't have a need for multiple ifs & conds like mine.

I also didn't realise the "vlax-curve-" functions work on enames so that's good to know. 


Glad to help out :). Another added benefit of passing enames to the curve functions is it's faster!

(setq e (car (entsel)))
(setq o (vlax-ename->vla-object e))
(benchmark '((vlax-curve-getstartpoint e)(vlax-curve-getstartpoint o)))
;;;_$ 
;;;Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s):
;;;
;;;    (vlax-curve-getStartPoint E).....1125 / 4.57 <fastest>
;;;    (vlax-curve-getStartPoint O).....5141 / 1.00 <slowest>
;;;
;;; 
;;;; 1 form loaded from #<editor "<Untitled-3> loading...">
;;;_$ 

As @ВeekeeCZ stated, the (x) in the conditional statement returns the value of the DXF code when the point checks don't pass. If it is left out you will have a list of 'nils' ( and two points ) which then will fail to entmod.

0 Likes
Message 15 of 15

11706013
Participant
Participant

@ronjonp wrote:

Glad to help out :). Another added benefit of passing enames to the curve functions is it's faster!

(setq e (car (entsel)))
(setq o (vlax-ename->vla-object e))
(benchmark '((vlax-curve-getstartpoint e)(vlax-curve-getstartpoint o)))
;;;_$ 
;;;Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s):
;;;
;;;    (vlax-curve-getStartPoint E).....1125 / 4.57 <fastest>
;;;    (vlax-curve-getStartPoint O).....5141 / 1.00 <slowest>
;;;
;;; 
;;;; 1 form loaded from #<editor "<Untitled-3> loading...">
;;;_$ 

As @ВeekeeCZ stated, the (x) in the conditional statement returns the value of the DXF code when the point checks don't pass. If it is left out you will have a list of 'nils' ( and two points ) which then will fail to entmod.


Thanks guys for the helpful information. And thank you to everyone who contributed to helping me on this. Genuinely Appreciated.

 

Cheers.

0 Likes