TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: cmwade77 on October 28, 2010, 12:30:55 PM

Title: AutoStacking
Post by: cmwade77 on October 28, 2010, 12:30:55 PM
Ok, we are switching to stacked fractions here (finally).

So, I have a couple of challenges to come up with solutions to:

I have some ideas where to start on the second one, but I have no clue for the first one. If anyone has any ideas, I would love to hear them.

Correction: I thought I had an idea of where to start on the second one, but the method doesn't work, so any ideas there would be appreciated as well.
Title: Re: AutoStacking
Post by: Lee Mac on October 28, 2010, 12:58:01 PM
With regards to first one, I believe the settings are stored here:

Code: [Select]
(strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT")
Don't quote me on that though...

As for the second, I should imagine you could use a RegExp expression to replaces strings matching something like (\S)/(\S), then replace it with {$1#$2} or similar..

Title: Re: AutoStacking
Post by: hermanm on October 28, 2010, 01:38:15 PM
Quote
Find an easy way (LISP routine is preferred) to change all fractions to be stacked fraction

For DIMENSIONs without overridden text, it should be as easy as changing the fraction type in the dimension style.

For text overrides in DIMENSIONs, & MTEXT, you will first need to decide what the relative height of the fractions will be, and what type of fraction bar.

So, for example, if you want the relative height of the fractions to be 0.75, with a diagonal fraction bar,

3/8 becomes -> {\H0.75x;\S3#8;}

You will need to find  the n/m type fractions & substitute the stacked fraction representation.
Title: Re: AutoStacking
Post by: dgorsman on October 28, 2010, 02:07:56 PM
You may want to make sure all required fractions are available in the font you are using in order to support non-MTEXT entities like attributes.  I seem to remember the OOTB RomanS.shx not having the "3/4" symbol defined, among others.
Title: Re: AutoStacking
Post by: cmwade77 on October 28, 2010, 03:57:22 PM
Actually, with modern stacking that is not an issue any more, AutoCAD now takes and makes the first number a superscript and the second number a subscript and adjusts the / between them. This is one of the reasons that stacked fractions are not accepted here.
Title: Re: AutoStacking
Post by: cmwade77 on October 28, 2010, 07:15:36 PM
Ok, here is what I have so far, please see the attached screenshot for an example of what happens to the text....any ideas?
Title: Re: AutoStacking
Post by: Lee Mac on October 28, 2010, 08:17:59 PM
Did you use the curly braces?

EDIT: Sorry, didn't see you attached the code...
Title: Re: AutoStacking
Post by: hermanm on October 28, 2010, 09:21:19 PM
you forgot to escape the backslash preceding the H:

Code: [Select]
"{\H0.7x;\\S"

here is a more compact way of testing for a numerical character:

Code: [Select]
(defun isdigit (char)
  (if (> 58 (ascii char) 47) char nil)
)
Title: Re: AutoStacking
Post by: Lee Mac on October 28, 2010, 09:33:53 PM
This needs a lot more error trapping, but this is where I was going with the Regular Expression usage:

Code: [Select]
(defun c:test ( / RegEx i ss e )
  (vl-load-com)
  ;; © Lee Mac 2010

  (setq RegEx (vlax-create-object "VBScript.RegExp"))

  (if (setq i -1 ss (ssget "_:L" '((0 . "MTEXT"))))
   
    (while (setq e (ssname ss (setq i (1+ i))))
      (vla-put-TextString (vlax-ename->vla-object e)
        (LM:RegExReplace RegEx "{\\H0.7x;\\S$1#$2;}" "-?(\\d+)/(\\d+)" (LM:GetTextString e))
      )
    )
  )

  (vlax-release-object RegEx)
  (princ)
)

(defun LM:RegExReplace ( reg new pat str )
  ;; © Lee Mac 2010
  (mapcar '(lambda ( prop value ) (vlax-put-property reg prop value)) '(pattern global ignorecase) (list pat actrue acfalse))
  (vlax-invoke reg 'replace str new)
)

(defun LM:GetTextString ( ent )
  ;; © Lee Mac 2010
 
  (  (lambda ( string )
       (mapcar
         (function
           (lambda ( pair )
             (if (vl-position (car pair) '(1 3))
               (setq string (strcat string (cdr pair)))
             )
           )
         )
         (entget ent)
       )
       string
     )
    ""
  )
)
Title: Re: AutoStacking
Post by: hermanm on October 28, 2010, 11:13:18 PM
Cool, Lee :)

Probably want to prefix the string with center justification code:

(strcat "\\A1;" <yourstring>)
Title: Re: AutoStacking
Post by: Lee Mac on October 29, 2010, 06:54:05 AM
Cool, Lee :)

Probably want to prefix the string with center justification code:

(strcat "\\A1;" <yourstring>)

Thanks Herman  8-)
Title: Re: AutoStacking
Post by: cmwade77 on October 29, 2010, 11:36:28 AM
you forgot to escape the backslash preceding the H:

Code: [Select]
"{\H0.7x;\\S"

Thank you, I can't believe that I missed it.

Lee,

I like your code, but I definitely do not understand it; however, we will often have fractions like: 12/15

Now here comes the challenge:
We will also have factions like: 2-12/15
These need to have the dash removed and the 12/15 stacked


Ok, I think I got it, including getting rid of the dash, I do need some more testing, so please let me know what you think, I have attached the code here.
Title: Re: AutoStacking
Post by: Lee Mac on October 29, 2010, 12:23:04 PM
Code updated to allow for the dash  :-)
Title: Re: AutoStacking
Post by: cmwade77 on October 29, 2010, 12:57:35 PM
Lee,

The only issue I had was that it would not stack: 123/256 for example, can you replicate this? It woul only stack one number before and after the /
Title: Re: AutoStacking
Post by: Lee Mac on October 29, 2010, 01:00:41 PM
Lee,

The only issue I had was that it would not stack: 123/256 for example, can you replicate this? It woul only stack one number before and after the /

Ah yes, I was only testing with single digits....

Updated.
Title: Re: AutoStacking
Post by: cmwade77 on October 29, 2010, 01:32:20 PM
Lee, I think your name appears in our customization more than mine.   :-D

Thank you, I think i understand some of your code, but I don't understand the following bits of your code:
Code: [Select]
(setq RegEx (vlax-create-object "VBScript.RegExp"))
(LM:RegExReplace RegEx "{\\H0.7x;\\S$1#$2;}" "-?(\\d+)/(\\d+)" (LM:GetTextString e))


(defun LM:RegExReplace ( reg new pat str )
  ;; © Lee Mac 2010
  (mapcar '(lambda ( prop value ) (vlax-put-property reg prop value)) '(pattern global ignorecase) (list pat actrue acfalse))
  (vlax-invoke reg 'replace str new)
)
Title: Re: AutoStacking
Post by: Lee Mac on October 29, 2010, 01:35:58 PM
That's the part that uses Regular Expressions to make the replacements, Joe Burke introduced me to those whilst working on the Batch Find & Replace program.

I use this reference:

http://msdn.microsoft.com/en-us/library/yab2dx62%28VS.85%29.aspx (http://msdn.microsoft.com/en-us/library/yab2dx62%28VS.85%29.aspx)
Title: Re: AutoStacking
Post by: cmwade77 on October 29, 2010, 01:39:52 PM
Wow, I am going to have to look into that further, when I have more time. Right now, I am trying to catch up with the standards changes that my boss approved (finally) and trying to get "real work" out....LOL
Title: Re: AutoStacking
Post by: cmwade77 on October 29, 2010, 02:50:08 PM
With regards to first one, I believe the settings are stored here:

Code: [Select]
(strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT")
Don't quote me on that though...

As for the second, I should imagine you could use a RegExp expression to replaces strings matching something like (\S)/(\S), then replace it with {$1#$2} or similar..



Yes, that is indeed where it is stored, here is what I have:
* EDIT: I got it working now:
Code: [Select]
(if (/= (vl-registry-read (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT") "AutoStack") 1)
(vl-registry-write (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT") "AutoStack" 1)
)
(if (/= (vl-registry-read (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT") "ConvertStackToArch") 1)
(vl-registry-write (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT") "ConvertStackToArch" 1)
)
(if (/= (vl-registry-read (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT") "TrimLeadingStackBlank") 1)
(vl-registry-write (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT") "TrimLeadingStackBlank" 1)
)
Title: Re: AutoStacking
Post by: Lee Mac on October 29, 2010, 06:49:28 PM
lol why not set a variable:

Code: [Select]
(setq root (vl-registry-read (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\MTEXT"))
Save you some typing  :-D

I suppose you could also use an expression like this, but it makes it less readable:

Code: [Select]
(mapcar
  (function
    (lambda ( key value )
      (if (/= value (vl-registry-read root key))
        (vl-registry-write root key value)
      )
    )
  )
  '("AutoStack" "ConvertStackToArch" "TrimLeadingStackBlank")
  '(1 1 1)
)
Title: Re: AutoStacking
Post by: Crank on October 30, 2010, 03:52:42 PM
Didn't try this, but is it necessary to read the key first? Can't you just write to the register:
Code: [Select]
(vl-registry-write root "AutoStack" 1)
(vl-registry-write root "ConvertStackToArch" 1)
(vl-registry-write root "TrimLeadingStackBlank" 1)
Title: Re: AutoStacking
Post by: cmwade77 on November 02, 2010, 11:29:04 AM
Didn't try this, but is it necessary to read the key first? Can't you just write to the register:
Code: [Select]
(vl-registry-write root "AutoStack" 1)
(vl-registry-write root "ConvertStackToArch" 1)
(vl-registry-write root "TrimLeadingStackBlank" 1)

I don't like writing to the registry if the values are already correctly set.....too many writes to the registry causes problems with windows.
Title: Re: AutoStacking
Post by: Crank on November 02, 2010, 12:00:10 PM
[...] too many writes to the registry causes problems with windows.
Windows also checks the key/value first. If the value is already 1 then nothing happens. :)
Title: Re: AutoStacking
Post by: cmwade77 on November 02, 2010, 12:30:25 PM
Ok, I didn't know that, I just wanted to avoid the possibility of extra writes.
Title: Re: AutoStacking
Post by: cmwade77 on November 03, 2010, 01:41:50 PM
This needs a lot more error trapping, but this is where I was going with the Regular Expression usage:

Code: [Select]
(defun c:test ( / RegEx i ss e )
  (vl-load-com)
  ;; © Lee Mac 2010

  (setq RegEx (vlax-create-object "VBScript.RegExp"))

  (if (setq i -1 ss (ssget "_:L" '((0 . "MTEXT"))))
    
    (while (setq e (ssname ss (setq i (1+ i))))
      (vla-put-TextString (vlax-ename->vla-object e)
        (LM:RegExReplace RegEx "{\\H0.7x;\\S$1#$2;}" "-?(\\d+)/(\\d+)" (LM:GetTextString e))
      )
    )
  )

  (vlax-release-object RegEx)
  (princ)
)

(defun LM:RegExReplace ( reg new pat str )
  ;; © Lee Mac 2010
  (mapcar '(lambda ( prop value ) (vlax-put-property reg prop value)) '(pattern global ignorecase) (list pat actrue acfalse))
  (vlax-invoke reg 'replace str new)
)

(defun LM:GetTextString ( ent )
  ;; © Lee Mac 2010
  
  (  (lambda ( string )
       (mapcar
         (function
           (lambda ( pair )
             (if (vl-position (car pair) '(1 3))
               (setq string (strcat string (cdr pair)))
             )
           )
         )
         (entget ent)
       )
       string
     )
    ""
  )
)

Lee,

This code works well, but I can't seem to get it to work with MLEADERs. Please note that I have tried removing the filter and just selected the mleaders to experiment with. Any ideas on how to accomplish this? The formatting is the same as for MTEXT.


EDIT: I think I got it, please see attached code and let me know if there is a better way to handle this.
Title: Re: AutoStacking
Post by: cmwade77 on November 09, 2010, 12:05:32 PM
Ok, one more question on this, does anyone have any ideas on how to modify this to work with tables?

I am going to keep hacking at it, but haven't been able to get anywhere yet.