Adding Arc Function to Current Lisp

Adding Arc Function to Current Lisp

Travis.Biddle
Advocate Advocate
1,302 Views
19 Replies
Message 1 of 20

Adding Arc Function to Current Lisp

Travis.Biddle
Advocate
Advocate

I have a lisp that reads TXT files and draws lines, points and places text based on the information found in the TXT file.  It works great, HUGE thank you to @Kent1Cooper !  I would like to add the drawing of the ARCs that are also found in the TXT files.  The LISP has the ARC command started on lines 86-88, just needs a little bit added to work.  I have attached the lisp as well as a sample TXT file.  Can anyone take a look and help out? I have tried, but am not able to get it to work.

0 Likes
Accepted solutions (1)
1,303 Views
19 Replies
Replies (19)
Message 2 of 20

hak_vz
Advisor
Advisor

I guess @Kent1Cooper will gladly make changes to the lisp code and add what you have requested.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 3 of 20

Kent1Cooper
Consultant
Consultant

In the data line for an ARC, you have this kind of thing:

ARC, XS=1002.54, YS=921.77, ZS=50.8, XE=1002.54, YE=1036.07, ZE=50.8, XC=1002.54, YC=978.92, ZC=-50.8, R=57.15, V=A

I assume those are coordinates of the Arc's Start, End and Center locations.  But what's the V=A at the end?

Kent Cooper, AIA
0 Likes
Message 4 of 20

Travis.Biddle
Advocate
Advocate

@Kent1Cooper Yes, you are correct.. and the V=A can be ignored. 

XS, YS, ZS (start x,y,z any Z-Value can just be ignored or set to 0) then XE, YE, ZE (end x,y,z), then XC, YC, ZC (center x,y,z,), R is Radius, and then V=A which can be ignored.

ARC, XS=1002.54, YS=921.77, ZS=50.8, XE=1002.54, YE=1036.07, ZE=50.8, XC=1002.54, YC=978.92, ZC=-50.8, R=57.15, V=A

0 Likes
Message 5 of 20

john.uhden
Mentor
Mentor

@Travis.Biddle 

Just curious...

With coordinates to only 2 places, the distances from center to start and end are liekly not to agree with the radius or even each other.  What is Kent to do, use an average?

One way that would work out mathematically is to find the center by triangulating from the ends using the radius, thereby holding the ends and the radius but shifting the center a tiny amount.

Now he could iterate the value of the radius to get the center as close as possible to its published coordinates, but if this exercise isn't for a Haldron Collider, then I guess you can skip the iterations.

John F. Uhden

0 Likes
Message 6 of 20

Kent1Cooper
Consultant
Consultant

And another question:  By "start" and "end" in the letter headings for coordinate values, does it always and only mean those terms in AutoCAD's method of storing Arc information, that is, with the Arc progressing counterclockwise from the start to the end?  If not, is there some reliable way to decide which of the two possible Arcs to draw between them?  Always the one that's less than 180° sweep?  What if the sweep is exactly 180°?

Kent Cooper, AIA
Message 7 of 20

Travis.Biddle
Advocate
Advocate

And another question:  By "start" and "end" in the letter headings for coordinate values, does it always and only mean those terms in AutoCAD's method of storing Arc information, that is, with the Arc progressing counterclockwise from the start to the end? YES.

 

I think using Start, End, Center input will work perfect and can ignore the radius.  Do you see any problem with that?  If the distance from center to start does not equal the radius, that is not a problem for me.

0 Likes
Message 8 of 20

john.uhden
Mentor
Mentor

@Travis.Biddle,

Good... CCW.

Yes there is still a problem with coordinates to 2 places.

The distance from center to start will most likely not equal the distance from center to end, nor equal the radius.

So, you have several options...

1.  Hold the center and start; take the radius from them; and locate the end via (polar center (angle center end) radius)

2.  Hold the center and end; take the radius from them; and locate the start via (polar center (angle center start) radius)

3.  Triangulate from the start and end, holding the radius, to locate the center.

4.  Average the two distances from center to start and center to end to use as the radius and triangulate to locate the center as in #3.

5.  Average the radius and the two distances from center to start and center to end to use as the radius and triangulate to locate the center as in #3.

6.  Compute the delta between the start and end radials.

     Hold the chord distance between the start and end.

     Rearrange the formula C=2Rsin(delta/2) to determine R=C/2sin(delta/2)

     Triangulate using R to locate the center. (of course that will change the delta slightly)

 

Triangulation can be performed using an arc-arc intersect (see functions below).  Since there are two solutions, you take the one nearest to the given center.

  ;;------------------------------------------------------
  ;; Function to return the arccos of an angle in radians:
  ;;
  (defun @acos (cosine / sine)
     (cond
        ((zerop cosine)(* pi 0.5))
        ((<= cosine -1.0) pi)
        ((>= cosine 1.0) 0.0)
        (1 (atan (/ (sqrt (- 1.0 (expt cosine 2))) cosine)))
     )
  )
  ;;------------------------------------------------------
  ;; Function to return the arcsin of an angle in radians:
  ;;
  (defun @asin (sine / cosine)
     (setq cosine (sqrt (- 1.0 (expt sine 2))))
     (if (zerop cosine)(setq cosine 0.000000000000000000000000000001))
     (atan (/ sine cosine))
  )
  ;;----------------------------------------------------
  ;; Function to find a point common to 2 arcs,
  ;; given both centers and radii, and a nearest point:
  (defun @aai (rp1 r1 rp2 r2 near / base x ang a p1 p2)
     (setq base (distance rp1 rp2))
     (cond
        ((and (equal r1 0.0 fuzz)(equal r2 base fuzz)) rp1)
        ((and (equal r2 0.0 fuzz)(equal r1 base fuzz)) rp2)
        ((> (+ r1 r2) base)
           (setq x (/ (- (+ (* base base)(* r1 r1)) (* r2 r2)) base 2.0))
           (if (minusp x)
              (setq ang (angle rp2 rp1) x (- x))
              (setq ang (angle rp1 rp2))
           )
           (setq a (@acos (/ x r1))
                p1 (polar rp1 (+ ang a) r1)
                p2 (polar rp1 (- ang a) r1)
                p1 (if (< (distance p1 near)(distance p2 near)) p1 p2)
           )
           p1
        )
        (1 (prompt "\nInvalid. Radii too small."))
     )
  )

 

John F. Uhden

0 Likes
Message 9 of 20

Travis.Biddle
Advocate
Advocate

Option #1 will work perfectly.

0 Likes
Message 10 of 20

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:

.... you have several options...

1.  Hold the center and start; take the radius from them; and locate the end via (polar center (angle center end) radius)

....

@Travis.Biddle wrote:

Option #1 will work perfectly.


A variant on that makes it quite easy if an Arc command is used [one of the types of benefits of the (command) function over something like (entmake)].  The Arc command in start-center-end combination uses just the direction from the center to the specified endpoint to determine the sweep of the Arc -- it doesn't use the specified point itself.  For example, this draws a nice 90° Arc at 1-unit radius even though the specified endpoint is way the heck away from it all:

 

(command "_.arc" "1,0,0" "_c" "0,0" "0,173")

 

So there's no need even to calculate the radius from the start and center, much less use it in a (polar) function to calculate the endpoint.  The three known points can simply be used directly.

 

But I do find that it won't accept an XYZ point for the center or end [direction], but only XY, so it will work right only when the Z numbers are the same, as they are in the posted data examples.

Kent Cooper, AIA
0 Likes
Message 11 of 20

Travis.Biddle
Advocate
Advocate

The Z value can be ignored, everything being on Z0 is ideal for me anyways.

0 Likes
Message 12 of 20

Kent1Cooper
Consultant
Consultant

I hope the attached will do it, if I recall enough of what the earlier one was about [untested].

Kent Cooper, AIA
0 Likes
Message 13 of 20

john.uhden
Mentor
Mentor
@Kent1Cooper
You ARE the master of the command function.
Nice!

John F. Uhden

0 Likes
Message 14 of 20

Travis.Biddle
Advocate
Advocate

It loads and runs through with no errors, but does not draw any of the arcs.

0 Likes
Message 15 of 20

Kent1Cooper
Consultant
Consultant

@Travis.Biddle wrote:

It loads and runs through with no errors, but does not draw any of the arcs.


Since it doesn't suppress command echoing, does the command line report any attempt to draw them?  Are there any messages?

 

Is the current Layer turned on?  Does it draw all the other kinds of things?  Might it be drawing the Arcs somewhere other than where you expect to see them?

 

And since the ctrX and ctrY variables are not yet localized [as they should be ultimately], what do they contain afterwards?

Kent Cooper, AIA
0 Likes
Message 16 of 20

Travis.Biddle
Advocate
Advocate

Nothing in the command line

no errors

current layer is on

draws all lines and points and places text correctly

ther are no arcs in the drawing at all

0 Likes
Message 17 of 20

Kent1Cooper
Consultant
Consultant

What about those variables?  Type  !ctrX  and  !ctrY  to see whether they contain anything.

Kent Cooper, AIA
0 Likes
Message 18 of 20

Travis.Biddle
Advocate
Advocate

Sorry, both values are NIL after running

0 Likes
Message 19 of 20

Kent1Cooper
Consultant
Consultant
Accepted solution

Tabs vs. spaces probably.  I must have copied the wrong other-object-type example.  Try replacing this line:
((wcmatch (vl-string-trim " " txt) "ARC*")
with this:

((wcmatch (vl-string-trim "\t " txt) "ARC*")

Kent Cooper, AIA
0 Likes
Message 20 of 20

Travis.Biddle
Advocate
Advocate

Yep, that was it.  Works perfect, thank you so much!!

0 Likes