Point as Function's argument

Point as Function's argument

Anonymous
Not applicable
1,283 Views
12 Replies
Message 1 of 13

Point as Function's argument

Anonymous
Not applicable

Hello, I am trying to write a function to determine in which quadrant of a given shape a point is, with other words, which is the corner of the shape that is the nearest to the point.  

The shape is a closed polyline and doesn't have to be a rectangle. The point is a point entity. 

I need to embed the function in another function, so neither the point nor the polyline should be given per user's input. I thought I could set the point and the polyline as arguments of the function, but something doesn't seem to work. When I run the code I get the error:

error : improper DEFUN argument list : 56.6021110540261

where the number is the x coordinate of the point.

 

I guess the problem is that the point is actually a list of coordinates, and I don't know how to pass this argument to the function. Can somebody help? Thank you. 

Here's my code: 

 

(defun pospt (/pt bnd)
  (setq bminx (apply 'min (mapcar 'car (poly-pts bnd)))
        bmaxx (apply 'max (mapcar 'car (poly-pts bnd)))
        bminy (apply 'min (mapcar 'cadr (poly-pts bnd)))
        bmaxy (apply 'max (mapcar 'cadr (poly-pts bnd)))
  )
  (setq xllpt (car pt)
        yllpt (cadr pt))
  (if (and 
      (<(abs (- xllpt bmaxx))(abs (- xllpt bminx)))
      (<(abs (- yllpt bminy))(abs (- yllpt bmaxy)))
      )
      (setq pospt "bottom-right")
  (if (and 
      (>(abs (- xllpt bmaxx))(abs (- xllpt bminx)))
      (<(abs (- yllpt bminy))(abs (- yllpt bmaxy)))
      )
      (setq pospt "bottom-left")
  (if (and 
      (<(abs (- xllpt bminx))(abs (- xllpt bmaxx)))
      (>(abs (- yllpt bminy))(abs (- yllpt bmaxy)))
      )
      (setq pospt "top-left")
  (if (and 
      (<(abs (- xllpt bmaxx))(abs (- xllpt bminx)))
      (>(abs (- yllpt bminy))(abs (- yllpt bmaxy)))
      )
      (setq pospt "top-right")(setq pos "other")))))
  
)

 

Poly-pts is a function I found on the forum that returns a list with the vertices of the polyline. 

0 Likes
Accepted solutions (1)
1,284 Views
12 Replies
Replies (12)
Message 2 of 13

Kent1Cooper
Consultant
Consultant

Arguments need to be listed before  the slash in the parentheses following the function name:

 

(defun pospt (pt bnd / bminx bmaxx {...etc...})

 

and the other variables ought to be localized [listed after the slash], though not doing so shouldn't prevent it from working.

Kent Cooper, AIA
0 Likes
Message 3 of 13

Anonymous
Not applicable

@Kent1Cooper 

I change it as you suggest, but I have the same problem. 

This is how I am trying to invoke the function at the end: 

(setq posspt (vlax-invoke c_spc 'pospt (spt bobj))
        posllpt (vlax-invoke c_spc 'pospt (llpt bobj))
  )
0 Likes
Message 4 of 13

Kent1Cooper
Consultant
Consultant

I haven't worked with (vlax-invoke), but in the "basic" way to use a defined function, the arguments would not be put in parentheses:

(setq
  posspt (pospt spt bobj))
  posllpt (pospt llpt bobj))
)

Does it work that way, and/or if you remove the parentheses around the arguments in your version?

(setq
  posspt (vlax-invoke c_spc 'pospt spt bobj)
  posllpt (vlax-invoke c_spc 'pospt llpt bobj)
)

 

Kent Cooper, AIA
0 Likes
Message 5 of 13

Anonymous
Not applicable

@Kent1Cooper , unfortunately not. In the first case i get the error "no function definition <POSPT> ; expected FUNCTION at [eval] occurred", in the second case it doesn't recognize the 'pospt function "Automation Error. Method [POSPT] not available occurred". Which makes sense, because I think this way of writing works only with native functions (maybe?). 

0 Likes
Message 6 of 13

Moshe-A
Mentor
Mentor

@Anonymous 

 

the arguments for (vlax-invoke) should be in a list. puting the arguments in parentheses is not enough cause lisp take it like calling a function so it should be '(spt bobj) or (list spt bobj) 😀

 

enjoy

moshe

 

(setq posspt  (vlax-invoke c_spc 'pospt '(spt  bobj))
      posllpt (vlax-invoke c_spc 'pospt '(llpt bobj))
)

 

 

 

0 Likes
Message 7 of 13

Anonymous
Not applicable

@Moshe-A , thank you, I wasn't sure where to put the apostrophe. 

Still I get the same error message "Method [POSPT] not available". Should I declare also the argument in the "pospt" funcuion as a list somehow?

0 Likes
Message 8 of 13

ВeekeeCZ
Consultant
Consultant
Accepted solution

Here's the sub and the test.

 

 

(defun c:Test ( / :pospt bnd pnt pos)


  
  (defun :pospt (pt bnd / pts bminx bminy bmaxx bmaxy xllpt yllpt)

    (setq pts (mapcar 'cdr (vl-remove-if '(lambda (x) (/= (car x) 10)) (entget bnd)))
	  bminx (apply 'min (mapcar 'car pts))
	  bmaxx (apply 'max (mapcar 'car pts))
	  bminy (apply 'min (mapcar 'cadr pts))
	  bmaxy (apply 'max (mapcar 'cadr pts))	  
	  xllpt (car pt)
	  yllpt (cadr pt))
    
    (cond ((and (< (abs (- xllpt bmaxx)) (abs (- xllpt bminx)))
		(< (abs (- yllpt bminy)) (abs (- yllpt bmaxy))))
	   "bottom-right")
	  
	  ((and (> (abs (- xllpt bmaxx)) (abs (- xllpt bminx)))
		(< (abs (- yllpt bminy)) (abs (- yllpt bmaxy))))
	   "bottom-left")
	  
	  ((and (< (abs (- xllpt bminx)) (abs (- xllpt bmaxx)))
	     (> (abs (- yllpt bminy)) (abs (- yllpt bmaxy))))
	   "top-left")
	  
	  ((and (< (abs (- xllpt bmaxx)) (abs (- xllpt bminx)))
	     (>(abs (- yllpt bminy)) (abs (- yllpt bmaxy))))
	   "top-right")
	  
	  (T "other")))


  ; -----------------------------------------------------------------------------------
  
  (if (and (setq bnd (car (entsel "\nGet a poly: ")))
	   (setq pnt (getpoint "\nPic a point"))
	   (not (terpri))
	   )
    (setq pos (:pospt pnt bnd)))
  
  )

 

0 Likes
Message 9 of 13

Anonymous
Not applicable

@ВeekeeCZ , Thanks that works nicely. I still don't get how to embed your function into mine. 

I loaded your sub and then tried to call the function as you do in the "test" part.

(setq posspt (:pospt spt bobj))
(setq posllpt (:pospt llpt bobj))

 

Now I get a new error message: bad argument type <#<VLA-OBJECT IAcadLWPolyline 0000000020BFFF40>> ; expected ENTITYNAME at [entget] occurred? Can you tell me why? 

0 Likes
Message 10 of 13

ВeekeeCZ
Consultant
Consultant

Because your pospt func is calling another poly-pts func. But I've replaced poly-pts with my own code.

 

(poly-pts bnd)

vs

(mapcar 'cdr (vl-remove-if '(lambda (x) (/= (car x) 10)) (entget bnd))

 

And while yours is working with obj, mine with ename.

 

 
0 Likes
Message 11 of 13

Anonymous
Not applicable

@ВeekeeCZ , it must be something else, because I deleted my part from the code and added yours. So there is no "poly-pts" anymore. 

 

The polyline is defined a couple of lines above with

(setq bobj (vlax-ename->vla-object (car (entsel "\nSelect Boundary : "))))

 

and the points llpt and spt through:

(setq spt (vlax-get lobj 'center)) [where lobj is the last inserted circle]

(setq llpt (vlax-curve-getpointatdist nobj (/ dst1 2))) [where nobj is a line]

0 Likes
Message 12 of 13

Anonymous
Not applicable

@ВeekeeCZ and you were right about the ename vs object stuff. I changed bobj to ename using the

"vlax-vla-object->ename" method and now it works, thank you very much! 

0 Likes
Message 13 of 13

ВeekeeCZ
Consultant
Consultant

@Anonymous wrote:

@ВeekeeCZ and you were right about the ename vs object stuff. I changed bobj to ename using the

"vlax-vla-object->ename" method and now it works, thank you very much! 


 

Good. Also can be fixed the other way around - get back your sub and remove my code:

 

  (defun :pospt (pt bnd / pts bminx bminy bmaxx bmaxy xllpt yllpt)

    (setq pts (poly-pts bnd)
	  bminx (apply 'min (mapcar 'car pts))
	  bmaxx (apply 'max (mapcar 'car pts))
	  bminy (apply 'min (mapcar 'cadr pts))
	  bmaxy (apply 'max (mapcar 'cadr pts))	  
	  xllpt (car pt)
	  yllpt (cadr pt)) ....

 

0 Likes