Author Topic: Dynamic drawing and substitution of grread-function  (Read 37279 times)

0 Members and 1 Guest are viewing this topic.

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Dynamic drawing and substitution of grread-function
« on: March 17, 2006, 12:26:27 PM »
That is my small contribution for lisp-programmers. :)
I hope this function will be useful:
Code: [Select]
;;
;; Alexander Rivilis, DynDraw\DynDraw.lsp
;; For book N.Poleshchuk.
;; "AutoCAD: Application Development, Tuning and Customization" 2006
;;
;;--------------------------------------------------------------------
;;                           (DynDraw)
;;--------------------------------------------------------------------
;;
;; Call:
;;  (dyndraw
;;    <call_back>      - name of callback-function (STR)
;;    <input_prompt>   - prompt string (STR)
;;    <keyword_list>   - keyword string (as initget-string) (STR)
;;    <input_flag>     - input parameters flag (INT)
;;    <cursor_type>    - type of cursor (INT)       
;;    <base_point>     - base point or nil
;;  )
;;
;; Parameters and its value:
;;
;;  1) <call_back>
;;     String with name of callback-function. Function *MUST* be registered
;;     with help of: (vl-acad-defun '<call_back>)
;;     
;;     This function has only one parameter. Depending on <input_flag>
;;     its can be:
;;     1) (X Y Z)      - point,    if <input_flag> is acqurePoint
;;     2) REAL         - distance, if <input_flag> is acqureDist
;;     3) REAL         - angle,    if <input_flag> is acqureAngle
;;     4) STR          - keyword   if <keyword_list> is not empty
;;                       other string - if <input_flag> is AcceptOtherInputString
;;
;;     Function *MUST* return one of values:
;;     1) nil          - exit;
;;     2) (X Y Z)      - point - change current point;
;;     3) (list ...)   - list - as list of dyndraw-finction
;;                       for changing all parameters;
;;                       параметров;
;;     4) STR          - for exit and returning STR;
;;     5) T            - for continue without changing;
;;                     
;;  2) <input_prompt>
;;     Simple prompt as for all getXXXX - functions.
;;
;;  3) <keyword_list> 
;;     String of keywords, as for (initget) function;
;;
;;  4) <input_flag>   
;;     Input flag - mast be the sum of one or more  of next values
;;     
;;
;;     GovernedByOrthoMode             1
;;     NullResponseAccepted            2
;;     DontEchoCancelForCtrlC          4
;;     DontUpdateLastPoint             8
;;     NoDwgLimitsChecking            16
;;     NoZeroResponseAccepted         32
;;     NoNegativeResponseAccepted     64
;;     Accept3dCoordinates           128
;;     AcceptMouseUpAsPoint          256
;;     AnyBlankTerminatesInput       512
;;     InitialBlankTerminatesInput  1024
;;     AcceptOtherInputString       2048
;;
;;     and only one of next value:
;;
;;     acqurePoint        0  -  return point;
;;                           
;;     acqureDist      8192  -  return distance;
;;       
;;     acqureAngle    16384  -  return angle;
;;                             
;;
;;  5) <cursor_type>
;;     Type of cursor (INT) - one of next values:
;;     NoSpecialCursor      -1      No special cursor specified
;;     Crosshair             0      Full screen cross hair
;;     RectCursor            1      Rectangular cursor
;;     RubberBand            2      Rubber band line
;;     NotRotated            3      (AutoCAD internal use only)
;;     TargetBox             4      Target Box type
;;     RotatedCrosshair      5      (AutoCAD internal use only)
;;     CrossHairNoRotate     6      Crosshairs forced non-rotated
;;     Invisible             7      Invisible cursor
;;     EntitySelect          8      Entity selection target cursor
;;     Parallelogram         9      Parallelogram cursor
;;     EntitySelectNoPersp  10      Pickbox, suppressed in persp
;;     PkfirstOrGrips       11      Auto-select cursor
;;
;;  6) <base_point>
;;     Base point or nil - for current cursor position.
;;
;; Function return one of next values:
;;     1) (X Y Z)      - point,    if <input_flag> is acqurePoint
;;     2) REAL         - distance, if <input_flag> is acqureDist
;;     3) REAL         - angle,    if <input_flag> is acqureAngle
;;     4) STR          - string,   from callback-function
;;     5) nil          - user abort
;;
;;The Particularities of the use and remarks:
;; 1) callback-function may not use interactive functions in all cases except
;;    it parameter is string (keyword)
;; 2) If this function is using for dynamic redrawing of database resident entities
;;    then in callback-function these entities must be updating with (entupd) or
;;    (vla-Update).
;; 3) If you using (grdraw) and/or (grvecs),
;;    you do not forget calling (redraw) for refreshing graphic window.
;;--------------------------------------------------------------------

;;--------------------------------------------------------------------
;;      Testing program for DynDraw
;;--------------------------------------------------------------------
(defun C:DYN_TEST ( / p_prev p_base p min_step
                      ang dist p1 p2 p3 _bm _ce
                  )
  ;; Minimal distance between points
  (setq min_step 1e-6)
  (if (null dyndraw) (progn
    (arxload "dyndraw.arx")
  )) ;_endof if progn
  ;;
  (setq _bm (getvar "blipmode") _ce (getvar "cmdecho"))
  (setvar "blipmode" 0) (setvar "cmdecho" 0)
  ;; Registering callback-function
  (vl-acad-defun 'dyn_call_back)
  (setq p (getvar "LASTPOINT"))
 
  (while
    (and dyndraw p (/= (type p) 'STR)
         (= (type (setq p (getpoint "\nBase point (ENTER - exit): "))) 'LIST))
    (setq p_base p p_prev p)
    (setq p
      (dyndraw
         ;; Name of callback - finction
         "dyn_call_back"
         ;; Prompt string
         "\nSelect point [Base point]: "
         ;; Keyword string
         "B _ B"   
         ;; Input flag
         (+ 2 128 2048) ;; Allow entering empty and 3D-points
         ;; Cursor type
         2 ;;  RubberBand
         ;; Base point (in UCS)
         p
      )
    )
    (redraw)
   
    (if (= (type p) 'LIST) (progn
      ;; Adding to databse
      (setq ang   (angle p_base p)
            dist  (* (distance p_base p) (sqrt 2))
            p1    (polar p (+ ang (* pi 0.75)) dist)
            p2    (polar p1 (+ ang (* pi 1.25)) dist)
            p3    (polar p2 (+ ang (* pi 1.75)) dist)
      )
      (command "_.undo" "_begin")
      (command "_.pline" "_none" p "_w" 0 0 "_none" p1  "_none" p2  "_none" p3 "_c")
      (command "_.undo" "_end")
    )) ;_endof if progn
  ) ;_endof while
  (if (= (type p) 'STR)
    (princ (strcat "\nUser input string: <" p ">"))
  )

  (setvar "blipmode" _bm) (setvar "cmdecho" _ce)
  (princ)
) ;_endof defun
;;--------------------------------------------------------------------
;;               Example of callback function
;;--------------------------------------------------------------------
(defun dyn_call_back (p / p1 p2 p3)
 (cond
  ((= (type p) 'STR) ;; User select a keyword
    (redraw) ;; Clear screen
    (cond
     ((= p "B") ;; User want to change base point
      (if (setq p (getpoint p_base "\nSelect new base point: "))
        (setq p_base p
              p  (list
                  "dyn_call_back"
                  "\nSelect new point: "
                  "" ;; No keywords
                  (+ 2 128 2048) ;; Allow entering empty and 3D-points
                  2 ; RubberBand
                  p
                 )
         )
      )
     )
     (T
      ;; Return this string
      (princ (strcat "\nUnknown keyword <" p ">!!!"))
     )
    ) ;_endof cond
  )
  ((= (type p) 'LIST) ;; Dragging with point
    (if (null p_base) (setq p_base p p_prev p))
    (if (and p_prev (> (distance p_prev p) min_step)) (progn
      (setq p_prev p)
      (setq input p
            ang   (angle p_base p)
            dist  (* (distance p_base input) (sqrt 2))
            p1    (polar input (+ ang (* pi 0.75)) dist)
            p2    (polar p1 (+ ang (* pi 1.25)) dist)
            p3    (polar p2 (+ ang (* pi 1.75)) dist)
       )
       (redraw) ;; Clear screen
       (grdraw input p1 -1)
       (grdraw p1 p2 -1)
       (grdraw p2 p3 -1)
       (grdraw p3 input -1)
    ))
  )
 ) ;_endof cond
 p
) ;_endof defun

Last version: http://www.maestrogroup.com.ua/support/dyndraw.zip
« Last Edit: March 28, 2012, 02:04:50 AM by Alexander Rivilis »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Dynamic drawing and substitution of grread-function
« Reply #1 on: March 17, 2006, 06:22:16 PM »
Hi Alexander,
Interesting code !

Is the ARX for AC2004, 05 and 06 ?
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Dynamic drawing and substitution of grread-function
« Reply #2 on: March 18, 2006, 04:01:21 AM »
Hi Alexander,
Interesting code !
Is the ARX for AC2004, 05 and 06 ?
Yes. :) This code is only example of using dyndraw-function.
With help of (grread) we can not using menu, object snap, etc.
With (dyndraw) we can use all above. 
P.S.: I've reattached arx file for AutoCAD 2002 and AutoCAD 2004...2006


« Last Edit: March 18, 2006, 04:48:12 AM by Rivilis »

zoltan

  • Guest
Re: Dynamic drawing and substitution of grread-function
« Reply #3 on: March 25, 2006, 09:16:43 AM »
This is a really awesome piece of work.   I was working on something like this using GrRead, but It could not do the OSNAPS and menues like this.

My question:
If the callback function trows an error, how do you stop the DynDraw function for contiuing to call the callback function?
I can't put a breakpoint in the callback function to trace it.

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Dynamic drawing and substitution of grread-function
« Reply #4 on: March 25, 2006, 10:18:20 AM »
If the callback function trows an error, how do you stop the DynDraw function for contiuing to call the callback function?
I can't put a breakpoint in the callback function to trace it.
Oh! It is very difficult question. Callback-function must be error-free because error in it may crash AutoCAD.
As I think you can not trace this function - it was called from ObjectARX application with worldDraw() method of custom class and debuger can not provide tracing of such type of function.
Try to catch errors with help of (vl-catch-all-apply ...) function.

If callback-function return Nil - DYNDRAW stop calling callback-function end also exit with Nil value.
« Last Edit: March 25, 2006, 10:52:02 AM by Rivilis »

zoltan

  • Guest
Re: Dynamic drawing and substitution of grread-function
« Reply #5 on: March 25, 2006, 11:23:46 AM »
Thank you.  I quess I just have to make sure that the call-back function works.

Can you explain in detail all of the input flags? (at least the not-so-obvious ones)

Does AnyBlankTerminatesInput have to be set in order for the callback function to end the loop by reterning nil?

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Dynamic drawing and substitution of grread-function
« Reply #6 on: March 25, 2006, 11:51:40 AM »
Can you explain in detail all of the input flags? (at least the not-so-obvious ones)
It will be a hard work! :)
Does AnyBlankTerminatesInput have to be set in order for the callback function to end the loop by reterning nil?
No! AnyBlankTerminatesInput - this flag mean that if user press blank - input of string is terminated.
Sush as (getstring) do it.

zoltan

  • Guest
Re: Dynamic drawing and substitution of grread-function
« Reply #7 on: March 26, 2006, 08:44:35 AM »
When the user hits escape at the prompt for a point, the DynDraw function ends and returns nil to the calling function.  At this point the top level program should exit because the user canceled the command.  If the user hits enter or space bar at the prompt to accept a default value, the DynDraw function exits and returns nil to the calling function.  Is there a way to differentiate between the two?

Could you make the DynDraw function accept a default value as a parameter, so if the user hits Enter or Space at the prompt, the DynDraw function will return the default value and if the user hits Escape to cancel the function, the DynDraw function exits and returns nil?

I have a callback function which when given a point, draws information to the screen.  When the callback function receives a string as an option keyword, much like you example, the user is asked to enter values for the input instead of picking a point on screen.  At this point the callback function returns nil so the DynDraw function will exit.  I have multiple options for the user to enter data that will end the DynDraw loop.  I need to be able to differentiate between their outputs.

If the call-back function returns nil, the DynDraw function should return the last value of the call-back functions parameter, so the main calling function can determine which option keyword ended the DynDraw loop.


Also, what do you think would be causing my use of the DynDraw function to not end when my call-back function returns nil?
I am using input flags 2 32 64.

Thanks in advance,
Zoltan
« Last Edit: March 26, 2006, 09:06:35 AM by zoltan »

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Dynamic drawing and substitution of grread-function
« Reply #8 on: March 27, 2006, 11:00:01 AM »
First of all I've reattached dyndraw.zip! Try new dyndraw.arx
When the user hits escape at the prompt for a point, the DynDraw function ends and returns nil to the calling function.  At this point the top level program should exit because the user canceled the command.  If the user hits enter or space bar at the prompt to accept a default value, the DynDraw function exits and returns nil to the calling function.  Is there a way to differentiate between the two?
Now if NullResponseAccepted or AcceptOtherInputString adding to <input_flag>, and you press Enter or blank - callback-function will be called with empty string (""), if escape - DynDraw return with nil.
Could you make the DynDraw function accept a default value as a parameter, so if the user hits Enter or Space at the prompt, the DynDraw function will return the default value and if the user hits Escape to cancel the function, the DynDraw function exits and returns nil?
I don't like adding new parameter to DynDraw. More simplest way is check parameter in callback function and if it is equal "" - use default value.

If the call-back function returns nil, the DynDraw function should return the last value of the call-back functions parameter, so the main calling function can determine which option keyword ended the DynDraw loop.
What about to try in callback-function save last value in *global* variable? :)

zoltan

  • Guest
Re: Dynamic drawing and substitution of grread-function
« Reply #9 on: March 27, 2006, 11:19:56 AM »
Thanks for the update. I will try it.

Is the ARX you reattached the 2002 or 2006 version?

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Dynamic drawing and substitution of grread-function
« Reply #10 on: March 27, 2006, 01:24:14 PM »
Is the ARX you reattached the 2002 or 2006 version?
I've reattached both versions.
« Last Edit: March 27, 2006, 03:52:33 PM by Rivilis »

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Dynamic drawing and substitution of grread-function
« Reply #11 on: April 01, 2006, 03:40:16 PM »
I've done some modification of dyndraw and re-post it in first message of this topic.

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Dynamic drawing and substitution of grread-function
« Reply #12 on: April 04, 2006, 06:26:57 AM »
New modifications and bugfixes (with help of Evgeniy Elpanov):
1) When error occur in callback-function dyndraw exit with nil value.
2) Debugger can debug callback-function.
« Last Edit: April 04, 2006, 09:15:14 AM by Rivilis »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Dynamic drawing and substitution of grread-function
« Reply #13 on: April 04, 2006, 08:42:01 AM »
Thanks for sharing this routine Rivilis. :-)
« Last Edit: April 04, 2006, 09:05:49 AM by CAB »
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: Dynamic drawing and substitution of grread-function
« Reply #14 on: April 04, 2006, 08:52:00 AM »
Thanks fopr sharing this routine Rivilis. :-)
I very hope this routine will be usefull for advanced VisualLisp programmers. :)
Next modification will be adoptation for AutoCAD 2007 - Done!
« Last Edit: April 04, 2006, 09:03:57 AM by Rivilis »