Author Topic: Point inside curve - crash with LM:inside-p  (Read 1115 times)

0 Members and 1 Guest are viewing this topic.

Peter2

  • Swamp Rat
  • Posts: 654
Point inside curve - crash with LM:inside-p
« on: February 08, 2022, 01:46:23 PM »
In a lot of postings is the code "LM:inside-p" by Lee - BTW: Thanks a lot for it!

Here is a current posting, including the "speed-up" by Marco
http://www.theswamp.org/index.php?topic=41837.msg603147#msg603147

My problem is: In a drawing I have a situation where the original-routine stops at a special point with an error
Code - Auto/Visual Lisp: [Select]
  1. "; Fehler: Fehlerhafter Argumenttyp: numberp: nil"
- and I can't see why. The version from Marco has no problems and returns the correct result.
I add the drawing with the polyline as border and two points in it  - the red for the "problem" and the green for just an example. If someone is curious to find out what happens - every hint is appreciated.

Problems in Acad Map 2018, works fine in Bricscad 21
« Last Edit: February 11, 2022, 03:50:47 AM by Peter2 »
Peter

AutoCAD Map 3D 2023 German (so some technical terms will be badly retranslated to English)
BricsCAD V23

ribarm

  • Gator
  • Posts: 3296
  • Marko Ribar, architect
Re: Point inside cureve - crash with LM:inside-p
« Reply #1 on: February 08, 2022, 03:09:46 PM »
If you are in need to do checkings of very large set of points and you need it to perform fast and reliable, here is what I used to do (programming for hipped roofs posted at download section at CadTutor site)...

Do very small offset of initial POLYLINE - or some other 2D curve - you need to make sure it's curve and its 2D (not REGION or ???)...
Assing curve to pol variable : (setq pol (car (entsel "\nPick boundary...")))
Firstly create VLA-OBJECT(curve-vla-object) : (setq obj (vlax-ename->vla-object pol)) ...
(function - (vla-offset obj -0.001) ) ... Then get resulting entity with (setq e1 (entlast))... Then make another offset now with positive factor : (vla-offset obj 0.001)... Then get resulting entity with (setq e2 (entlast))... Then do simple comparison of areas of e1 and e2...

Code: [Select]
(if (< (vlax-curve-getarea e1) (vlax-curve-getarea e2))
  (progn
    (setq offpol e1)
    (entdel e2)
  )
  (progn
    (setq offpol e2)
    (entdel e1)
  )
)

Now you have offpol entity that represents offset of initial boundary and offset was done Inside (area is smaller)...

So as far as you need to know thats all you have to do and nothing more in need to do checkings and you do it just once at the beginning of routine you write...

Now to the point of checkings weather point is inside or not :

Consider creating this sub :

Quote
(defun inside-p ( pt )
  (< (distance pt (vlax-curve-getclosestpointto offpol pt)) (distance pt (vlax-curve-getclosestpointto pol pt)) )
)

That's all you need... It is fast, reliable and can do very good job for very large point set you need to perform checkings to...

At the end of routine, simply remove dummy offpol entity with (entdel offpol), but from my experience, the best is that you put this line into (*error* nil) handler so that when you terminate deliberately or routine crashed during programming, dummy entity get erased for sure...

Your XXX routne...

Quote
(defun c:XXX ( / *error* inside-p [other subs localized] ... ... cmde pol obj e1 e2 offpol [other variables localized] ... ... )

  (vl-load-com) ;;; Load Acivex extensions (VLA functions)

  (defun *error* ( m )
    ...
    (if cmde (setvar 'cmdecho cmde)) ;;; if you used cmdecho change during running routine...
    ... ;;; other variables the same way reset...
    ...
    (if (and offpol (not (vlax-erased-p offpol)))
      (entdel offpol)
    )

    ...
    (command-s "_.UNDO" "_E") ;;; if you set UNDO grouping/marking as tasks for routine inside main body... (command-s) function has its main purpose here to avoid possible VVC error - since 2015 version of AutoCAD... Sometimes it can work and with (vl-cmdf) or (command), but they are not to be placed in error handler - this is place for (command-s) like its stated in documentation...
    (if m (prompt m))
    (princ)
  )

  (defun inside-p ( pt )
    (< (distance pt (vlax-curve-getclosestpointto offpol pt)) (distance pt (vlax-curve-getclosestpointto pol pt)) )
  )

  ...
  Other subs (defuns)
  ...

  --- MAIN ---
  (setq cmde (getvar 'cmdecho))
  (setvar 'cmdecho 0)
  get and set other system variables at beginning [NOTE : At the beginning its important to get values of sysvars and store them in ordinary lisp variables that should be localized and eventually reset through error handler like "cmde" shown here... You can set values of system variables as desired at any point in main body and change them as you need in orther to make functionality of routine as much as desirable as possible - function for setting is (setvar 'sysvar value)]
  ...
  (if (= 8 (logand 8 (getvar 'undoctl)))
    (vl-cmdf "_.UNDO" "_E)
  )
  (vl-cmdf "_.UNDO" "_G")
  ...
  (setq pol (car (entsel "\nPick lwpolyline boundary...")))
  (setq obj (vlax-ename->vla-object pol))
  (vla-offset obj -0.001)
  (setq e1 (entlast))
  (vla-offset obj 0.001)
  (setq e2 (entlast))
  (if (< (vlax-curve-getarea e1) (vlax-curve-getarea e2))
    (progn
      (setq offpol e1)
      (entdel e2)
    )
    (progn
      (setq offpol e2)
      (entdel e1)
    )
  )

  Now consider in main body using some UNDO tasks...

  ...
  (vl-cmdf "_.UNDO" "_M") ;;; undo mark
  ...
  Now do something with point inside boundary...
  (if (inside-p p)
    ... then do something...
    ... else do something else...
  )
  ...
  something was processed or drawn
  ...
  (vl-cmdf "_.UNDO" "_B") ;;; back to previous undo mark...
  ...

 Those things may occur many times you need...

  ...
  (vl-cmdf "_.UNDO" "_M") ;;; undo mark
  ...
  Now do something with point inside boundary...
  (if (inside-p p)
    ... then do something...
    ... else do something else...
  )
  ...
  something was processed or drawn
  ...
  (vl-cmdf "_.UNDO" "_B") ;;; back to previous undo mark...
  ...

  (while [testexpression] ... ;;; looping or something - (foreach xxx [lst with xxx elements] ... ) ...  - (repeat [number-integer] ... ) ...

    ...
    (vl-cmdf "_.UNDO" "_M") ;;; undo mark
    ...
    Now do something with point inside boundary...
    (if (inside-p p)
      ... then do something...
      ... else do something else...
    )
    ...
    something was processed or drawn
    ...
    (vl-cmdf "_.UNDO" "_B") ;;; back to previous undo mark...
    ...

   Those things may occur many times you need...

    ...
    (vl-cmdf "_.UNDO" "_M") ;;; undo mark
    ...
    Now do something with point inside boundary...
    (if (inside-p p)
      ... then do something...
      ... else do something else...
    )
    ...
    something was processed or drawn
    ...
    (vl-cmdf "_.UNDO" "_B") ;;; back to previous undo mark...
    ...

  ) ;;; end of (while) or other looping type - or multile nested loopings [(while expression1 ... (while expression2 ... ) ... )] [(foreach a lst1 ... (foreach b lst2 ... ) ... )] [(repeat num1 ... (repeat num2 ... ) ... )] ... Nesting in any form-combination [while, foreach, repeat] ...

  ...
  (vl-cmdf "_.UNDO" "_M") ;;; undo mark
  ...
  Now do something with point inside boundary...
  (if (inside-p p)
    ... then do something...
    ... else do something else...
  )
  ...
  something was processed or drawn
  ...
  (vl-cmdf "_.UNDO" "_B") ;;; back to previous undo mark...
  ...

 Those things may occur many times you need...

  ...
  (vl-cmdf "_.UNDO" "_M") ;;; undo mark
  ...
  Now do something with point inside boundary...
  (if (inside-p p)
    ... then do something...
    ... else do something else...
  )
  ...
  something was processed or drawn
  ...
  (vl-cmdf "_.UNDO" "_B") ;;; back to previous undo mark...
  ...

  At the end if you wish you make prompt for informing user that for undo to state before routine start - user must type "UNDO" "Back" at command line
  (prompt "\nFor back, type \"UNDO\" \"Back\"...")
  ...

  Here at the very end of main routine you place this line
  (*error* nil) ;;; calling error handler with reseting options for correct ending of routine ... (you can avoid (princ) as it was placed already in error halder as last line...)
)

HTH.
« Last Edit: February 08, 2022, 06:43:36 PM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Peter2

  • Swamp Rat
  • Posts: 654
Re: Point inside curve - crash with LM:inside-p
« Reply #2 on: February 14, 2022, 08:21:32 AM »
Thanks @ribarm

I think I got it!
Peter

AutoCAD Map 3D 2023 German (so some technical terms will be badly retranslated to English)
BricsCAD V23