Copy an entity along a direction with a given distance

Anonymous

Copy an entity along a direction with a given distance

Anonymous
Not applicable

Hello, 

as absolute Newby, I'm trying to write a Lisp routine for copying an object (a circle) along a direction with a specific distance. The user should be prompted to insert the distance and to click for the direction. The object I need to be copied is the last created object and it should be copied until a boundary is reached (a polyline). I already wrote a function (myself, and adapting some material online) for recognizing whether a point is inside or outside the boundary. I know is an appreciated praxis to post also at least a piece of code, but I'm currently in front of the white page. 

Maybe somebody can give me a hint on how to start? 

Thank you in advance

 

PS: I have nothing against arrays, but I need the objects to be independent of each other and the path doesn't exist as an entity yet when running the routine. 

0 Likes
Reply
Accepted solutions (1)
1,733 Views
7 Replies
Replies (7)

Kent1Cooper
Consultant
Consultant

I would start by having the User select the boundary Polyline.  The routine can find the Circle if it's the last entity, with (entlast), and extract its center from its entity data [do you know how to do that?].  You can use (getdist) to ask for the distance, and (getangle) to ask for the direction, and you can use the Circle's center in the (getangle) function so you get a "rubber-band" line when picking the direction, though you can also just type in a direction as an angle in current Units.

 

Then I would start a (while) loop.  Use (polar), starting from the center and using the direction and angle, to find a potential  place to Copy the Circle to.  Apply your is-it-inside-the-boundary function to check whether that place is inside, and if so, Copy the last object from its center to the new location.  Then the (while) function would step back and try again, checking whether the next potential location, (polar)'d from the previous one, is still within the boundary, and if so, again copying the last object [not the original Circle, after the first Copy] in the same way.  When the next potential location fails the test of being inside the boundary, the (while) loop will stop.

 

Question:  The above description is in terms of Circle centers.  But if a potential next location is within the boundary, but less than a Circle radius from it, then part of the Circle will extend outside the boundary.  Is that acceptable?  It could check whether the location at the-distance-plus-the-radius  is still inside, before Copying, which would keep the last Circle fully inside the boundary if  the direction is approaching the boundary perpendicularly.  But with boundary edges at other angles, that test wouldn't always prevent at least some part of a Circle crossing the boundary.

 

Kent Cooper, AIA
0 Likes

dlanorh
Advisor
Advisor
Is the start point of the copy the centre of the last circle?

I am not one of the robots you're looking for

0 Likes

Anonymous
Not applicable

That's interesting, I didn't know the (polar) function.

I still don't know how to extract data from an entity but I'm confident I'll find some explanation online ^^. Something with (entget) I guess? I will try and post my many to come questions on this thread. Thank you very much. 

Ah, and no, it's not a problem if a portion of a circle gets outside the boundary, the centre point should remain inside. 

0 Likes

Anonymous
Not applicable

yes, it's probably the most logical option. 

0 Likes

dlanorh
Advisor
Advisor
Accepted solution

A start. This works but requires a distance, the boundary to be selected and the vector to be selected.

 

(vl-load-com)

(defun c:CAV (/ *error* a_app c_doc c_spc sv_lst sv_vals lobj dst bobj spt vpt nobj ept len rdst ipt cobj)

  (defun *error* ( msg )
    (mapcar 'setvar sv_lst sv_vals)
    (if (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*")) (princ (strcat "\nOops an Error : " msg " occurred")))
    (princ)
  );end_defun

  (setq a_app (vlax-get-acad-object)
        c_doc (vla-get-activedocument a_app)
        c_spc (vlax-get-property c_doc (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace))
        sv_lst (list 'cmdecho 'osmode)
        sv_vals (mapcar 'getvar sv_lst)
        lobj (vlax-ename->vla-object (entlast))
  );end_setq

  (mapcar 'setvar sv_lst '(0 0))

  (initget 7)
  (setq dst (getreal "\nEnter Distance between object centers : ")
        bobj (vlax-ename->vla-object (car (entsel "\nSelect Boundary : ")))
        spt (vlax-get lobj 'center)
        vpt (getpoint spt "\nSelect Vector : ")
        nobj (vlax-invoke c_spc 'addray spt vpt)
        ept (vlax-invoke nobj 'intersectwith bobj acextendnone)
  )
  (vla-delete nobj)
  (setq nobj (vlax-invoke c_spc 'addline spt ept)
        len (vlax-get nobj 'length)
        rdst dst
  )
  (while (< rdst len)
    (setq ipt (vlax-curve-getpointatdist nobj rdst)
          cobj (vla-copy lobj)
          rdst (+ rdst dst)
    )
    (vlax-invoke cobj 'move spt ipt)
  )
  (vla-delete nobj)
  (mapcar 'setvar sv_lst sv_vals)
  (princ)
);end_defun

 

 

I am not one of the robots you're looking for

Anonymous
Not applicable

@dlanorh 

I'm amazed, thank you that's perfect! It'll take me a while to figure out what you did 🙂 

0 Likes

dlanorh
Advisor
Advisor

The first half sets up the lisp (error routine), collects information and gets the last entity (as an object) then its centre.

After that it basically inserts a ray, finds where it intersects with the boundary, deletes it then draws a line from the centre to the intersection point. After that it simply measures along the line using the specified distance then copies the last object  and moves the copy to the last measured point. At the end it deletes the line and resets if neccessary. 

I am not one of the robots you're looking for

0 Likes