Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Easy way to find a point on XLINE and LINE

20 REPLIES 20
SOLVED
Reply
Message 1 of 21
user_sf
2039 Views, 20 Replies

Easy way to find a point on XLINE and LINE

Hi,

 

I have two questions for experts

 

1) Is there an easy way in LISP to calculate a mid point of a line and get an X, Y, Z coordinates for this point? I know I can pull end points from the entity data

 

(setq current_line (entsel "\n Select line")

(setq point1 (cdr (assoc 10 (entget (car current_line)))))

(setq point2 (cdr (assoc 11 (entget (car current_line)))))

 

2) I also would like to find X,Y,Z coordinates of a point on an xline located, say, 20 units away from xline origination point.

 

 Your input is highly appreciated

20 REPLIES 20
Message 2 of 21
Lee_Mac
in reply to: user_sf

user_sf wrote:

1) Is there an easy way in LISP to calculate a mid point of a line and get an X, Y, Z coordinates for this point?

 

You can use the following function:

 

(defun mid ( p1 p2 )
    (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) p1 p2)
)

 

For example:

 

_$ (mid '(1.2 3.4 0.0) '(5.2 1.3 2.8))
(3.2 2.35 1.4)

 

Or, with a LINE:

 

(defun c:test ( / ent enx )
    (if (and (setq ent (car (entsel "\nSelect LINE: ")))
             (= "LINE" (cdr (assoc 0 (setq enx (entget ent)))))
        )
        (entmake (list '(0 . "POINT") (cons 10 (mid (cdr (assoc 10 enx)) (cdr (assoc 11 enx))))))
    )
    (princ)
)

 

user_sf wrote:

2) I also would like to find X,Y,Z coordinates of a point on an xline located, say, 20 units away from xline origination point.

 

Try the following function:

 

(defun xpoint ( enx dis )
    (mapcar '(lambda ( a b ) (+ a (* dis b))) (cdr (assoc 10 enx)) (cdr (assoc 11 enx)))
)

 

Call the above with the DXF data of your XLINE & the distance from the XLINE origin, e.g.:

 

(defun c:test ( / ent enx len )
    (if (and (setq ent (car (entsel "\nSelect XLINE: ")))
             (= "XLINE" (cdr (assoc 0 (setq enx (entget ent)))))
             (setq len (getdist "\nSpecify distance from origin: "))
        )
        (entmake (list '(0 . "POINT") (cons 10 (xpoint enx len))))
    )
    (princ)
)
Message 3 of 21
Kent1Cooper
in reply to: user_sf


@user_sf wrote:

.... 

1) Is there an easy way in LISP to calculate a mid point of a line and get an X, Y, Z coordinates for this point? I know I can pull end points from the entity data

 

(setq current_line (entsel "\n Select line"))

(setq point1 (cdr (assoc 10 (entget (car current_line)))))

(setq point2 (cdr (assoc 11 (entget (car current_line)))))

 

2) I also would like to find X,Y,Z coordinates of a point on an xline located, say, 20 units away from xline origination point.

....


1)  Another way to do it, without the need to extract point1 and point2:

 

(osnap (cadr current_line) "_mid")

 

Or, if you need point1 and point2 for some other reason, so you're getting them anyway:

 

(mapcar '/ (mapcar '+ point1 point2) '(2 2 2))

 

 

2)  Parameter values for Xlines are drawing unit lengths.  These will get those points in the two directions from the origination point:

 

(vlax-curve-getPointAtParam theXlineEntityName 20)

 

(vlax-curve-getPointAtParam theXlineEntityName -20)

 

[after doing (vl-load-com) if necessary]

Kent Cooper, AIA
Message 4 of 21
Lee_Mac
in reply to: Kent1Cooper

Kent1Cooper wrote:

1)  Another way to do it, without the need to extract point1 and point2:

 

(osnap (cadr current_line) "_mid")

 

Be careful with this method - it could return unexpected results when used in crowded areas of a drawing.

Message 5 of 21
user_sf
in reply to: Lee_Mac

Thank you. It should work. I will research on mapcar and lamdba tonight.
Message 6 of 21
user_sf
in reply to: Kent1Cooper

I like the second suggested approach for dealing with Q1. Followup to Q2 - Would I be able to use vlax functions in AutoLISP or would I have to do it in Visual? Thank you.
Message 7 of 21
stevor
in reply to: user_sf

Yes, vlax functions, and others, are available in any full version of Autocad. Autolisp and Vlisp run inside Autocad, no need to be in either of them.
S
Message 8 of 21
hgasty1001
in reply to: user_sf

Hi,

 

I prefer to do it with vlax functions:

 

(vl-load-com)

(defun GetMidPoint(ent)
  (vlax-curve-getPointAtParam ent 0.5)
)

(defun GetPointAtDistanceFromOrigin(ent dist)
  (vlax-curve-getPointAtDist ent dist)
) 

 

OBS:

The (vl-load-com) need to be called only once in the session

 

The first function takes ent as argument it should be an ENAME, but it will fail if ent it's not a curve, and may give an erroneous output if ent it's not a line.

 

Curve objects like lines, polylines, etc are parameterized curves, and for lines the start parameter is 0 and the end parameter is 1, and as lines are linear objects, the mid point will be positioned exactly at the value 0.5, this may not apply to others curve objects even with only one segment.

 

The second function is no needed at all, as it's only a rename to clarify that the distance is measured from the origin (dxf code 10)

 

Gaston Nunez

 

 

Message 9 of 21
Kent1Cooper
in reply to: hgasty1001


@hgasty1001 wrote:

....

 

,,,,
(defun GetMidPoint(ent) (vlax-curve-getPointAtParam ent 0.5) ) ,,,,

 

... for lines the start parameter is 0 and the end parameter is 1, and as lines are linear objects, the mid point will be positioned exactly at the value 0.5, ....

 


That's not the case with Lines.  The Parameter values are drawing units of length.  The end Parameter of a Line will be 1 only if the Line is exactly 1 drawing unit long.  The only thing I can think of off-hand for which that would find the midpoint would be a one-segment Polyline, but it would do so whether that is a line or an arc segment.
Kent Cooper, AIA
Message 10 of 21
Kent1Cooper
in reply to: Lee_Mac


@Lee_Mac wrote:

1)  Another way to do it, without the need to extract point1 and point2:

 

(osnap (cadr current_line) "_mid")

 

Be careful with this method - it could return unexpected results when used in crowded areas of a drawing.


Yes, and if it seems likely that this could be an issue [i.e. that you won't always be able to select your Line in a place clear of other objects within Osnap range], one thing that I have sometimes done is to set the APERTURE System Variable temporarily to the same size as the PICKBOX System Variable.  Presumably one is not going to select an object in a place where other objects are within the pick-box target range, so if the Osnap Aperture is no bigger than that, Object Snap wouldn't find what it's looking for in relation to any object other than the one selected.

Kent Cooper, AIA
Message 11 of 21
Lee_Mac
in reply to: Kent1Cooper


@Kent1Cooper wrote:

@Lee_Mac wrote:

1)  Another way to do it, without the need to extract point1 and point2:

 

(osnap (cadr current_line) "_mid")

 

Be careful with this method - it could return unexpected results when used in crowded areas of a drawing.


Yes, and if it seems likely that this could be an issue [i.e. that you won't always be able to select your Line in a place clear of other objects within Osnap range], one thing that I have sometimes done is to set the APERTURE System Variable temporarily to the same size as the PICKBOX System Variable.  Presumably one is not going to select an object in a place where other objects are within the pick-box target range, so if the Osnap Aperture is no bigger than that, Object Snap wouldn't find what it's looking for in relation to any object other than the one selected.


If there is even the smallest chance that this method could fail where other methods would not, I see no reason or advantage to suggesting this route to the OP - given that the entity name (and hence the entity DXF data) is readily available in both cases, simple coordinate manipulation of the two line endpoints should not fail for any reason, and will be entirely independent of the position of the line in the drawing with no need to alter any system variables whatsoever.

Message 12 of 21
hgasty1001
in reply to: Kent1Cooper

Ooooops, you are right.

 

 

 

Message 13 of 21
user_sf
in reply to: hgasty1001

I am still struggling finding a point along XLINE. I think my problem is that I've not dealt with vlax functions and don't know how to go about them. I figured I could get away by looking at assoc 10 and assoc 11 of the XLINE and then draw another line by repositioning UCS and then work with this line for my purposes, but I can't get the code to work all the time....

 

(setq x_line (entsel "\n Pick xline"))
(setq xline_pt1 (cdr (assoc 10 (entget (car x_line)))))
(setq xline_pt2 (cdr (assoc 11 (entget (car x_line)))))

(command "ucs" "_w")

(command "ucs" "_o" xline_pt1)

(command "line" '(0 0 0) xline_pt2 "")

 

This code for some reason doesn't seem to work all the time. Does anybody know why? All I need to do is to find a point on xline. Thank you.

 

 

Message 14 of 21
Kent1Cooper
in reply to: user_sf


@user_sf wrote:

....

(command "ucs" "_w")

(command "ucs" "_o" xline_pt1)

(command "line" '(0 0 0) xline_pt2 "")

 

This code for some reason doesn't seem to work all the time. Does anybody know why? All I need to do is to find a point on xline. Thank you.


The xline_pt1 and xline_pt2 variables will be in World coordinates.  The Line command will take input in the current Coordinate System.  So if you want to do it that way, you would need to (trans)-late the WCS values into the current Coordinate System:

 

(command "line" '(0 0 0) (trans xline_pt2 0 1) "")

 

But you could also just leave it in the WCS, and do:

 

(command "line" xline_pt1 xline_pt2 "")

Kent Cooper, AIA
Message 15 of 21
Kent1Cooper
in reply to: user_sf


@user_sf wrote:

I am still struggling finding a point along XLINE. I think my problem is that I've not dealt with vlax functions and don't know how to go about them. .... 

....

(setq xline_pt1 (cdr (assoc 10 (entget (car x_line)))))
(setq xline_pt2 (cdr (assoc 11 (entget (car x_line)))))

.... 


In explanation of my suggestion from earlier:

 

(vlax-curve-getPointAtParam theXlineEntityName 20)  ... and ... -20)

 

This function gets the Point along the entity at the specified Parameter value from the start point.  What the Parameter values represent varies with entity type, but for Xlines and Lines, one drawing unit of length adds 1 to the Parameter value.  For Xlines, the 0 Parameter is the defining "start" or origin point, the same as the (assoc 10) value in the entity data list.  Distances along it from there can be positive or negative, with the positive direction being toward the second defining point, i.e. the (assoc 11) value in the entity data.

 

Since Parameter values are the same as distances from the origin, the same could be done with a different function:

(vlax-curve-getPointAtDist theXlineEntityName 20)  ... and ... -20)

 

You can give (vlax-curve...) functions either the entity name [in this case, (car x_line), or it can be extracted from an (ssget) selection set or a list of entity names, or, when appropriate, with (entlast)] or the conversion of that into a VLA object with (vlax-ename->vla-object).

 

Don't be thrown by the "curve" in the function names -- "curve" objects in VLA terms are anything with linearity, whether curved or straight: Lines, Arcs, Circles, Polylines of any type, Ellipses, Splines, Rays, Xlines....

 

Another way you could do it without (vlax-curve...) functions:

 

(polar xline_pt1 (angle xline_pt1 xline_pt2) 20)

and either

(polar xline_pt1 (angle xline_pt1 xline_pt2) -20)

or

(polar xline_pt1 (+ (angle xline_pt1 xline_pt2) pi) 20)

Kent Cooper, AIA
Message 16 of 21
user_sf
in reply to: Kent1Cooper

Thank you, Kent. The way I understand is that in XLINE property 10 is the origin of the construction line in WCS and property 11 is the unit direction vector also in WCS. I may be wrong but I think 11 is really a point that specifies the direction and not the actual point along the line. This is the reason why I don't do trans for this point while I am doing trans for xline_pt1. '(0 0 0) should be the same as trans for xline_pt1. xline_pt2 is the just a point from origin of UCS in this case. What do you think?

Message 17 of 21
user_sf
in reply to: Kent1Cooper

Hi Kent,

 

I feel that this solution should work but while I think I understand how to code in AutoLISP, I am absolutely lost with Visual Lisp. When I use vlax functions, should I do something else to make those functions available for the program? What I usually do is write an AutoLISP routine in Notepad++, save the file and then just grab it and drop it to the AutoCAD open window. This way AutoLISP function becomes available for me. What is the procedure for vlax? Any help is much appreciated.

Message 18 of 21
Kent1Cooper
in reply to: user_sf


@user_sf wrote:

... 10 is the origin of the construction line in WCS and property 11 is the unit direction vector also in WCS. ....


You're right -- the 11 value is a unit vector relative to the WCS 10 value, not the selected WCS point defining the direction as I had incorrectly assumed [I didn't look closely enough].  In that case, the only thing I can think of that might make your original code not work all the time is that you may have some running Object Snap mode(s) on.

 

My (polar)-based suggestions should then be:

 

(polar xline_pt1 (angle '(0 0 0) xline_pt2) 20)

and either

(polar xline_pt1 (angle '(0 0 0) xline_pt2) -20)

or

(polar xline_pt1 (+ (angle '(0 0 0) xline_pt2) pi) 20)

 

and they should work without first aligning the UCS with the Xline.

Kent Cooper, AIA
Message 19 of 21
Kent1Cooper
in reply to: user_sf


@user_sf wrote:

.... When I use vlax functions, should I do something else to make those functions available for the program? ....


Put

 

(vl-load-com)

 

in, either within any program that uses such functions, or in acaddoc.lsp so that they are loaded in every drawing you open.

Kent Cooper, AIA
Message 20 of 21
user_sf
in reply to: Kent1Cooper

Thank you, Kent. vlax works. This is by far the most elegant solution! I will be reading on Visual LISP.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost