Author Topic: Mtext Autostack conversion  (Read 1503 times)

0 Members and 1 Guest are viewing this topic.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10366
Mtext Autostack conversion
« on: March 21, 2013, 06:16:33 PM »
Looking at Lee's code here  http://www.theswamp.org/index.php?topic=35499.15

I was trying to detect only "\\S" fractions
Code: [Select]
(1 . "\\A1;2{\\H0.7x;\\S1#2;} X 2{\\H0.7x;\\S1#2;} X {\\H0.7x;\\S3/16;}\" ANGLE
8\" LONG W/ (2) {\\H0.7x;\\S5/8;}\"X4\" LAG SCREWS 3/4 not converted.")
Only this would be converted \\S3/16 & \\S5/8 and not this 3/4

So how to include the \\S ?
I tried this :
Code: [Select]
(LM:RegExReplace RegEx "$1#$2" "(\\S)(\\d+)/(\\d+)" (LM:GetTextString e))But I am missing something.
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.

Lee Mac

  • Seagull
  • Posts: 12270
  • London, England
Re: Mtext Autostack conversion
« Reply #1 on: March 21, 2013, 06:39:29 PM »
Try this CAB:
Code: [Select]
(defun c:stackchange ( / enx inc rgx sel )
    (if (setq sel (ssget "_:L" '((0 . "MTEXT") (1 . "*\\S*/*"))))
        (if (setq rgx (vlax-create-object "vbscript.regexp"))
            (progn
                (vlax-put-property rgx 'global     actrue)
                (vlax-put-property rgx 'ignorecase actrue)
                (vlax-put-property rgx 'multiline  actrue)
                (vlax-put-property rgx 'pattern "\\\\S([^/]+)/([^;]+);")
                (repeat (setq inc (sslength sel))
                    (setq enx (entget (ssname sel (setq inc (1- inc)))))
                    (entmod
                        (subst
                            (cons 1 (vlax-invoke rgx 'replace (cdr (assoc 1 enx)) "\\S$1#$2;"))
                            (assoc 1 enx)
                            enx
                        )
                    )
                )
                (vlax-release-object rgx)
            )
            (princ "\nUnable to interface with RegExp object.")
        )
    )
    (princ)
)
(vl-load-com)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10366
Re: Mtext Autostack conversion
« Reply #2 on: March 21, 2013, 06:55:51 PM »
Worked just right.

Now if I want to change the unstacked 3/4 to this {\\H0.7x;\\S3#4;}
in the same operation?
  I'm cooking dinner so I may be awhile before I get back.

Thanks in advance.  8-)
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.

Lee Mac

  • Seagull
  • Posts: 12270
  • London, England
Re: Mtext Autostack conversion
« Reply #3 on: March 21, 2013, 08:25:49 PM »
It's been a while since I've worked with Regular Expressions  :-P
This should be able to handle both cases:
Code: [Select]
(defun c:stackchange ( / enx inc rgx sel )
    (if (setq sel (ssget "_:L" '((0 . "MTEXT") (1 . "*#/#*"))))
        (if (setq rgx (vlax-create-object "vbscript.regexp"))
            (progn
                (vlax-put-property rgx 'global     actrue)
                (vlax-put-property rgx 'ignorecase actrue)
                (vlax-put-property rgx 'multiline  actrue)
                (vlax-put-property rgx 'pattern "(\\{\\\\H[^;]+;\\\\S)*(\\d+)/(\\d+)(;\\})*")
                (repeat (setq inc (sslength sel))
                    (setq enx (entget (ssname sel (setq inc (1- inc)))))
                    (entmod (subst (cons 1 (vlax-invoke rgx 'replace (cdr (assoc 1 enx)) "{\\H0.7x;\\S$2#$3;}")) (assoc 1 enx) enx))
                )
                (vlax-release-object rgx)
            )
            (princ "\nUnable to interface with RegExp object.")
        )
    )
    (princ)
)
(vl-load-com)

Assumptions:
  • Text matching #...#/#...# is considered a fraction.
  • 70% Text height is to be used for all fractions
« Last Edit: March 22, 2013, 07:33:21 AM by Lee Mac »

CAB

  • Global Moderator
  • Seagull
  • Posts: 10366
Re: Mtext Autostack conversion
« Reply #4 on: March 21, 2013, 10:03:50 PM »
Worked as advertised.  :-D

Regular Expressions are very powerful but can be tricky to use.
Thanks Lee.
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.

Lee Mac

  • Seagull
  • Posts: 12270
  • London, England
Re: Mtext Autostack conversion
« Reply #5 on: March 22, 2013, 07:30:43 AM »
Excellent, you're very welcome Alan  :-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10366
Re: Mtext Autostack conversion
« Reply #6 on: March 22, 2013, 06:28:17 PM »
Lee that saved me a lot of time today. About 100 mtext objects corrected.
I did run into a snag with large mtext objects & modified the code (see below).

trying to break down the expressions I got the following:
I also tried to add detection for number dash or number space before the fraction and if found
eliminate the space or dash, but this attempt failed.


Your pattern explanation
{\\H0.7x;\\S1#2;}    Target string within Mtext string

"(\\{\\\\H[^;]+;\\\\S)*(\\d+)/(\\d+)(;})*"   Pattern

"
(               >>-----> start of a subexpression  $1
  \\{\\\\H     match  {\H
  [^;]         H followed by anything except ;
  +            match previous expression any amount of times, so the ; stops the match
  ;            literal match of ;
  \\\\S)       match \S
 )             <-----<<  end of a subexpression
 *             Matches the previous character or subexpression zero or more times
 
 (\\d+)        group of numbers, subexpression  $2
 
 /             literal match of /
 
 (\\d+)        group of numbers, subexpression  $3
 
 (;})          subexpression  $4
  *            Matches the previous character or subexpression zero or more times
  "
 Note that * is needed to match "3/4" without stacking formatting and to add the formatting
 needed to properly starch that fraction
 
Replace with Pattern
"{\\H0.7x;\\S$2#$3;}"

"
{\\H0.7x;\\S   weather this was found or not use this replacement, this would be $1 if found
$2             reuse what was found
#              replace / with #
$3             reuse what was found
;}             weather this was found or not use this replacement, this would be $4 if found
"     



Revised Match Pattern
This includes proceeding numbers followed by a space or dash and eliminates the space or dash
but doesn't work 
"(\\d)[ -]?(\\{\\\\H[^;]+;\\\\S)*(\\d+)/(\\d+)(;})*"

Explanation
"(\\d)    any number but * does not work here
 [ -]?    match space or dash one or zero times

(\\{\\\\H[^;]+;\\\\S)*(\\d+)/(\\d+)(;})*"       same as previous example

Revised Replacement Pattern
"$1{\\H0.7x;\\S$3#$4;}"


Test string:
Code: [Select]
test 3/4 - 1/2" fraction should convert to {\\H0.7x;\\S3#4;} - {\\H0.7x;\\S1#2;}"
test 34 - 1/2" fraction  should convert to 34 - {\\H0.7x;\\S1#2;}"
test 3 1/2" fraction  should convert to 3{\\H0.7x;\\S1#2;}"
test 3-1/2" fraction  should convert to 3{\\H0.7x;\\S1#2;}"

Revised code
Code: [Select]
;;  CAB modified to work with >250 character Mtext
(defun c:FixFractions ( / enx inc rgx sel )
    (if (setq sel (ssget "_:L" '((0 . "MTEXT"))))
        (if (setq rgx (vlax-create-object "vbscript.regexp"))
            (progn
                (vlax-put-property rgx 'global     actrue)
                (vlax-put-property rgx 'ignorecase actrue)
                (vlax-put-property rgx 'multiline  actrue)
                ;(vlax-put-property rgx 'pattern "(\\{\\\\H[^;]+;\\\\S)*(\\d+)/(\\d+)(;})*")
                (vlax-put-property rgx 'pattern "(\\d)[ -]?(\\{\\\\H[^;]+;\\\\S)*(\\d+)/(\\d+)(;})*")
                (repeat (setq inc (sslength sel))
                    (setq obj (vlax-ename->vla-object (ssname sel (setq inc (1- inc))))
                          str (vla-get-textstring obj))
                  (and (wcmatch str "*#/#*")
                       ;(setq str (vlax-invoke rgx 'replace str "{\\H0.7x;\\S$2#$3;}"))
                       (setq str (vlax-invoke rgx 'replace str "$1{\\H0.7x;\\S$3#$4;}"))
                       (vla-put-textstring obj str)
                  )
                )
                (vlax-release-object rgx)
            )
            (princ "\nUnable to interface with RegExp object.")
        )
    )
    (princ)
)
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.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10366
Re: Mtext Autostack conversion
« Reply #7 on: March 22, 2013, 06:31:54 PM »
PS forgot about the possibility of a negative fraction -1/2 in which case the minus sign should remain.
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.

Lee Mac

  • Seagull
  • Posts: 12270
  • London, England
Re: Mtext Autostack conversion
« Reply #8 on: March 23, 2013, 08:03:45 PM »
Great dissection CAB!  8-)

For your new patterns, try the following code:
Code: [Select]
(defun c:stackchange ( / inc obj rgx sel str )
    (if (setq sel (ssget "_:L" '((0 . "MTEXT") (-4 . "<OR") (1 . "*#/#*") (3 . "*#/#*") (-4 . "OR>"))))
        (if (setq rgx (vlax-create-object "vbscript.regexp"))
            (progn
                (vlax-put-property rgx 'global     actrue)
                (vlax-put-property rgx 'ignorecase actrue)
                (vlax-put-property rgx 'multiline  actrue)
                (vlax-put-property rgx 'pattern "(?:(\\d)[ \\-])?(?:\\{\\\\H[^;]+;\\\\S)*(\\d+)/(\\d+)(?:;\\})*")
                (repeat (setq inc (sslength sel))
                    (setq obj (vlax-ename->vla-object (ssname sel (setq inc (1- inc))))
                          str (vla-get-textstring obj)
                    )
                    (vla-put-textstring obj (vlax-invoke rgx 'replace str "$1{\\H0.7x;\\S$2#$3;}"))
                )
                (vlax-release-object rgx)
            )
            (princ "\nUnable to interface with RegExp object.")
        )
    )
    (princ)
)
(vl-load-com)

The above should hopefully account for all cases described in this thread, but I've only tested it briefly so you may want to thoroughly put it through its paces before making use of it  :-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10366
Re: Mtext Autostack conversion
« Reply #9 on: March 23, 2013, 08:19:14 PM »
Thanks Lee,
In my quick test it does work but I will need some time to figure out the new pattern.
BTW this does not work in ACAD2006:
(if (setq sel (ssget "_:L" '((0 . "MTEXT") (-4 . "<OR") (1 . "*#/#*") (3 . "*#/#*") (-4 . "OR>"))))
Not sure why but this does work on small mtext.
(if (setq sel (ssget "_:L" '((0 . "MTEXT") (1 . "*#/#*"))))

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.

Lee Mac

  • Seagull
  • Posts: 12270
  • London, England
Re: Mtext Autostack conversion
« Reply #10 on: March 23, 2013, 08:30:14 PM »
Thanks Lee,
In my quick test it does work but I will need some time to figure out the new pattern.

Excellent, you're very welcome CAB  :-)
Ask if you have any questions regarding the pattern and I'll try my best to explain when I get some time.

BTW this does not work in ACAD2006:
(if (setq sel (ssget "_:L" '((0 . "MTEXT") (-4 . "<OR") (1 . "*#/#*") (3 . "*#/#*") (-4 . "OR>"))))
Not sure why but this does work on small mtext.
(if (setq sel (ssget "_:L" '((0 . "MTEXT") (1 . "*#/#*"))))

That's rather odd - that filter works for me, and I see no reason that the filter logic should fail (unless I've overlooked something), so perhaps it is a bug with earlier versions?

CAB

  • Global Moderator
  • Seagull
  • Posts: 10366
Re: Mtext Autostack conversion
« Reply #11 on: March 24, 2013, 12:01:01 AM »
Nicely Done Lee. 8-)

New Pattern Explanation
Code: [Select]
"(?:(\\d)[ \\-])?(?:\\{\\\\H[^;]+;\\\\S)*(\\d+)/(\\d+)(?:;\\})*"
"
(                >>-----> start of a subexpression
  ?:              Matches following pattern but does not save the match, that is, the match is not stored for possible later use.
            Pattern to match is a number followed by a space or dash,
  (\\d)        number - This is subexpression  $1 within a subexpression and the space or dash is forgotten due to the ?:
                note that only one number is acquired & proceeding numbers are left as is. This acquired number is re-established in the string as $1
  [ \\-]        space or dash, this is the part that is forgotten
)?               Matches the previous character or subexpression zero or one time

(               >>-----> start of a subexpression
  ?:              Matches following pattern but does not save the match, that is, the match is not stored for possible later use.

  \\{\\\\H     match  {\H
  [^;]         H followed by anything except ;
  +            match previous expression any amount of times, so the ; stops the match
  ;            literal match of ;
  \\\\S       match \S
 )             <-----<<  end of a subexpression
  *            Matches the previous character or subexpression zero or more times

 (\\d+)        group of numbers, subexpression  $2
 
 /             literal match of /
 
 (\\d+)        group of numbers, subexpression  $3

(?:              Matches following pattern but does not save the match, that is, the match is not stored for possible later use.
  ;\\})         subexpression literal match of ;}

*"

Replacement Pattern
"$1{\\H0.7x;\\S$2#$3;}"
« Last Edit: March 24, 2013, 03:53:48 PM 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.

Lee Mac

  • Seagull
  • Posts: 12270
  • London, England
Re: Mtext Autostack conversion
« Reply #12 on: March 24, 2013, 09:13:45 AM »
Cheers CAB  8-)
Great analysis of the Regular Expression pattern, I'm sure other members of the forum will greatly benefit from your dissection.