Programming Challenge No. 4

Programming Challenge No. 4

john.uhden
Mentor Mentor
5,157 Views
37 Replies
Message 1 of 38

Programming Challenge No. 4

john.uhden
Mentor
Mentor

Because of a recent post about offsetting inside/outside vs. left/right, your challenge is to write one (1) function that returns whether a given point is to the left or right of any curve.

It must take two (2) arguments:

p = point

e = entity name

It must return either

+ = right, or

- = left

For the sake of brevity, you may declare other locals.

I'm going to name mine LorR.  Another cool name would be +or-.

I (or someone) will post an official test drawing later 'cause right now I have to go buy a Christmas tree with my wife and son, who has brought along a chain saw in case we want to cut our own.  She found a place about 35 minutes away that has Douglas Firs and Noble Firs grown on site, so the tree WILL be fresh as opposed to being trucked across the country from Oregon.

John F. Uhden

0 Likes
5,158 Views
37 Replies
Replies (37)
Message 2 of 38

john.uhden
Mentor
Mentor

Change 1:

Your function must take two (2) arguments:

   handle = handle of entity already in the drawing

   p = point

Your function may still declare other locals.

My timer function will be altered to test for each of the curve types in the drawing using the same point provided in the timer.

I think the types will consist of one each of an Arc, Circle, Line, LWPolyline, Spline, Ray, Xline, and Ellipse.  Though I don't know about the Xline.  Like what direction is it going, the same as a pushmi-pullyu?

All will be 2D in the WCS.

I will try to make it so the last output for each timer will look something like...

(+ - + + - - + -)

Let's hope you all get the same result (and that mine matches too).

VELOCITAS VINCINT OMNIA

John F. Uhden

0 Likes
Message 3 of 38

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:

....

It must return either

+ = right, or

- = left

....


In what form?  As a text string "+" or "-"?  As the AutoLisp function somehow, such as applied in some longer code?  Something else?

Kent Cooper, AIA
0 Likes
Message 4 of 38

Sea-Haven
Mentor
Mentor
Accepted solution

1st choice

; left or right by Lee-mac.com

(defun ISL-R ( / ent pnt cpt der )
(if (and (setq ent (car (entsel)))
             (setq pnt (getpoint "\nPoint: "))
        )
		(progn
		(setq pnt (trans pnt 1 0))
    (setq cpt (vlax-curve-getclosestpointto ent pnt)
          der (vlax-curve-getfirstderiv ent (vlax-curve-getparamatpoint ent cpt))
    )
    (if (minusp (sin (- (angle cpt pnt) (angle '(0.0 0.0) der))))
        (princ "\nPoint is on the right.")
        (princ "\nPoint is on the left.")
    )
    (princ)
)
)
)
0 Likes
Message 5 of 38

Sea-Haven
Mentor
Mentor
Message 6 of 38

john.uhden
Mentor
Mentor
The actual function symbols + or -

John F. Uhden

0 Likes
Message 7 of 38

john.uhden
Mentor
Mentor

@lee-mac , @Sea-Haven , @Kent1Cooper 

(also @ronjonp, @pbejse, @doaiena, @hak_vz, @dbroad, et al.)

Please read the instructions again.

Your function is to take two (2) arguments:

1.  handle (it will be provided in the Challenge4.lsp file

2.  p (a point which will also be provided in the Challenge4.lsp file

It should return either the + or - function names literally, not as strings.

 

Hopefully, I will have successfully posted both Challenge4.lsp and Challenge4.dwg (notice, Ron, there is no # character).

Please read the Challenge4.lsp file as it contains instructions for use and the timer and c:TEST functions so you can do your own testing.  It also contains my 1st attempt for which I would be flattered if you improved upon it.

Please name your functions uniquely. perhaps with your initials as a suffix (as I did).

John F. Uhden

0 Likes
Message 8 of 38

john.uhden
Mentor
Mentor

I guess I should have explained better.

This function is not just for a challenge exercise.

It could be used by someone who prefers the use of vla-offset vs. (command "_.OFFSET" ...).

That way the programmer could determine the offset by...

(setq sign (fun_name e p))
(setq offset (sign offset))

In that usage it wouldn't take a handle as input but rather an ename. 

As an exercise, especially for timing, it must take a handle of an entity already in the drawing so that we can compare our functions on an even basis.

Notice in the Challenge4.lsp file I listed all the applicable handles, one for each object type that could be offset.

Um, are there any other object types that can be offset that I am missing?  I'd say nevermind 2DPolylines 'cause they are just old, BUT, wait a second, a splined or fit-curved LW becomes a 2DPolyline, which you can offset, so maybe I will add them.  Whaddya think?

John F. Uhden

0 Likes
Message 9 of 38

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:

....  I'd say nevermind 2DPolylines 'cause they are just old, BUT, wait a second, a splined or fit-curved LW becomes a 2DPolyline, which you can offset, so maybe I will add them.  Whaddya think?


I think they should be included, since they can be Offset.  But since they share an entity type name [e.g. for (ssget) filter-list purposes] with 3D Polylines which cannot be Offset even if they're planar, some check needs to be built in to avoid those while still allowing "heavy" 2D Polylines.

Kent Cooper, AIA
0 Likes
Message 10 of 38

john.uhden
Mentor
Mentor
@Kent1Cooper
Thank you for your response.
For real use the 3D vs. 2D check should/must be made before the function is
called, thus providing the function an applicable ename.
One could check the 70 code, or one could check the ObjectName, or one
could check if the Offset method is applicable-p.
For this exercise I am not including nonapplicable entities, so no check is
required within the function.
I will post new files.

John F. Uhden

0 Likes
Message 11 of 38

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:
....One could check the 70 code....

This seems to work to find and highlight Offsettable objects [including Splines, but see below] based on that [super-minimally tested]:


(sssetfirst nil

  (ssget "_X"

    '(

      (-4 . "<OR")

        (0 . "LINE,LWPOLYLINE,CIRCLE,ARC,RAY,XLINE,SPLINE")

        (-4 . "<AND")

          (0 . "POLYLINE")

          (-4 . "<NOT") (-4 . "&") (70 . 88) (-4 . "NOT>"); not 3D [8] or mesh [16 & 64]

        (-4 . "AND>")

      (-4 . "OR>")

    ); filter list

  ); ssget

); sssetfirst

 

But then there's the Spline question -- non-planar ones can't be Offset.  I looked up the 70-code entry for those, which lists bit codes up to 16, of which the presence of 8 means it's planar.  But I drew a non-planar Spline, and checked its entity data, and it has a DXF-70 value of 1024!  I'm not sure what to make of that, since [apart from the fact that all the listed bit values add up to only 31] 8 is a bit-code ingredient of 1024.  So when I took SPLINE out of the first list of entity types and put in code to check for planar Splines only [inside the OR wrapping]:

      (-4 . "<AND")
        (0 . "SPLINE") (-4 . "&") (70 . 8); planar
      (-4 . "AND>")

it "saw" that Spline, even though it is not planar.

Kent Cooper, AIA
0 Likes
Message 12 of 38

john.uhden
Mentor
Mentor
That's pretty good research and work, Kent.
Looks like you have found a new AutoCAD "feature."
I could say that I don't care because it's not pertinent to the
Left-or-Right function, but I do care, so maybe the
(vlax-method-applicable-p object 'Offset) is the best vetting mechanism for
weeding out nonqualified objects. Fortunately for me, I have never dealt
with nor plan ever to deal with a non-planar spline. Except if you can
treat it sorta like a 3D polyline, then it might be valuable for some more
realistic grading lines.

John F. Uhden

0 Likes
Message 13 of 38

john.uhden
Mentor
Mentor

@Kent1Cooper , @dbroad , @Sea-Haven , @hak_vz, @ronjonp, @doaiena, et al,

(Sorry BeekeeCZ, I can never remember your new ID.)

Based on @Kent1Cooper's suggestion I have revised the Challenge4.dwg and Challenge4.lsp files to include a Fit-curved 2D poly and a Splined 2D poly.

Please read messages #9, 10, 11, and 12.

Please use the new attached files in place of the old.

John F. Uhden

0 Likes
Message 14 of 38

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

....

But then there's the Spline question -- ....


CORRECTION:  It wasn't 1024 [which is a power of 2 itself], but something larger, and I don't still have the same one to check again.  I don't know what I did wrong before, but I tried some more, and this does seem to work, accepting all those no-question object types, and planar Splines and both "heavy" and "lightweight" 2D Polylines, but not non-planar Splines or 3D Polylines [even if planar].

(sssetfirst nil
  (ssget "_X"
    '( ; filter list
      (-4 . "<OR")
        (0 . "LINE,LWPOLYLINE,CIRCLE,ARC,ELLIPSE,RAY,XLINE")
        (-4 . "<AND")
          (0 . "POLYLINE")
          (-4 . "<NOT") (-4 . "&") (70 . 88) (-4 . "NOT>"); not 3D [8] or mesh [16 & 64]
        (-4 . "AND>")
        (-4 . "<AND")
          (0 . "SPLINE") (-4 . "&") (70 . 8); planar
        (-4 . "AND>")
      (-4 . "OR>")
    ); filter list
  ); ssget
); sssetfirst

It's helpful to be able to find qualifying things at one shot like that within (ssget), rather than to accept selection of some things that don't qualify, and then need to step through and check something [such as the Offsetting-available test] to disqualify them if appropriate and remove them from the selection.

Kent Cooper, AIA
0 Likes
Message 15 of 38

john.uhden
Mentor
Mentor
That's great, Kent, but losing a few milliseconds doesn't bother me very
much. If I were stepping through and checking things manually, then yes,
the filter would be critical.
Seriously, if what you have there really does the job, then it's important
for us all to know and use it.

John F. Uhden

0 Likes
Message 16 of 38

ВeekeeCZ
Consultant
Consultant
Accepted solution
@unnamed-smart-guy  wrote:
The offset method does not support RAYs.

 

Just re-posting a quick note. 

0 Likes
Message 17 of 38

john.uhden
Mentor
Mentor
@ВeekeeCZ
Woudja look at that!
Yet the Offset command does.
I guess the Autodesk programmers have better tools than the toothless saws
they give us to use.
No wonder Kent likes the command function so much.

John F. Uhden

0 Likes
Message 18 of 38

ВeekeeCZ
Consultant
Consultant
Accepted solution

@john.uhden wrote:

Because of a recent post about offsetting inside/outside vs. left/right, your challenge is to write one (1) function that returns whether a given point is to the left or right of any curve.

...

It must return either

+ = right, or

- = left

....


 

@unnamed-smart-guy  wrote:
The function you challenge us to write is in no relation to the vlax-offset method. While for LINEs and XLINEs your 'LorR-JFU func returns the correct sign for point-to-curve relation, the vlax-offset method offsets object to the opposite direction. See your drawing, greens are good, reds are bad.

 

Just re-posting another quick note. 

0 Likes
Message 19 of 38

Kent1Cooper
Consultant
Consultant

Well, I put a routine called LvsR-KC into the copy of Challenge4.lsp attached.  But when I run TEST, I get:

 

Command: TEST
*** LORR-JFU ***
Results: ((ARC -) (LINE +) (CIRCLE -) (ELLIPSE -) (LWPOLYLINE +) (SPLINE +) (RAY +) (XLINE -) (Fit Curved 2D +) (Spline Curved 2D -))
Elapsed time for 10000 iterations of all 8 handles: 2766 millisecs.
*** LVSR-KC ***; error: bad argument value: positive 0

 

I get the same error if I try the (timer) function with mine alone:

 

Command: (timer 'LvsR-KC 10000)

*** LVSR-KC ***; error: bad argument value: positive 0

 

Yet my routine works on its own if I set a handle and a point and feed them in:

Command: (setq handle (cdr (assoc 5 (entget (car (entsel))))))

Select object: "36" [I picked the Ray]

Command: (setq p (getpoint)) [I picked a point to the right of the Ray's direction]
(13.9238 8.8005 0.0)

Command: (LvsR-KC handle p)
+

 

So I'm wondering whether it's something in the (timer) function.  I don't know what "positive 0" signifies, but if that means it's looking for a positive number but being given 0 instead, I don't see any candidates for the function that could be triggering such an error, in either your code or mine.

 

 

Kent Cooper, AIA
0 Likes
Message 20 of 38

john.uhden
Mentor
Mentor

It's a disconnect between what the timer expects and what your function returns.

The timer expects just + [#<SUBR @0000027c9313fba8 +>]

Your function returns '+

I like your approach better, but I'm not changing horses midstream for the sake of the others (if there are any).

 

BTW, you had better look to see what happens when Adir = 10° and AtoP = 280°

John F. Uhden

0 Likes