Stacked fractions in a lisp routine

Stacked fractions in a lisp routine

cclinton
Contributor Contributor
997 Views
9 Replies
Message 1 of 10

Stacked fractions in a lisp routine

cclinton
Contributor
Contributor

With the help of ChatGPT, I have a working routine the does the following:

  1. Select two points to create a rectangle in memory - this rectangle shall not be drawn or printed, or should be erased after execution of the command

  2. Extract the width and height of the rectangle

  3. Add a user defined distance/dimension to the width and height of the rectangle

  4. Display the new width/height as mtext in the middle of the two points selected in step 1 in the format of, say xx x/x" x yy y/y"

The issue I'm having is in step 4. I'm trying to get the resulting measurement to stack the fraction and I can not figure out how to do it. See attached file for the code.

Any thoughts or ideas are greatly appreciated. Thank you.

0 Likes
998 Views
9 Replies
Replies (9)
Message 2 of 10

Kent1Cooper
Consultant
Consultant

Your string content has incorrect quotation marking and some meaningless empty strings.  Is the intent to have three-line Mtext with the "x" on a middle line between the width and height values?  Then I think your string needs to be formatted more like this:

  (setq text-string (strcat (rtos new-width 5 2) "\\Px\\P" (rtos new-height 5 2)))

[Replace the "\\P" hard-return parts with spaces to have one line.]  But that doesn't stack the fractions.  Sadly, (rtos) won't return with the encoding for that, which requires insertions of special coding characters in multiple locations within the string that it returns.  The 1-code entry for this:

Kent1Cooper_0-1721316921633.png

is like this:

(1 . "\\A1;123{\\H0.7x;\\S1/2;}\\Px\\P234{\\H0.7x;\\S3/4;}")

 

The red parts would need to be interspersed in between the "real" parts to get the stacked fractions.  Diagonal-stacked uses "#" instead of "/" between the fraction numbers.  It may be possible to work out how to include the special codes, looking for the "/" or "#" characters to identify fractions, but there's the complication [probably among others] that there may not be a fraction part that it should stack for either or both of the sizes.

 

Could you somehow achieve what you want using actual Dimensions instead of Mtext?  Those will do the stacked fractions as you like if the Style is set up for that.  A Style could be defined with both extension and both dimension lines suppressed. The "x" could be a Text object.  Some way to work out the positioning would be needed, but that may not be too hard.

Kent Cooper, AIA
Message 3 of 10

cclinton
Contributor
Contributor

Thank you for the response. That seems like a bit much to workout with my limited knowledge, but I'll take a close look at it.

 

With regard to your last part about using dimensions instead, this is what I am planning on using this for: I work for a window company. When we draw storefront and curtain wall frames, we dimension what is called the DLO (Day Light Opening) which is from inside of frame to inside of frame. From this DLO information we generate glass sizes based on the DLO dimension. This is mtext on a single line, rotated 45° in the area where the glass goes. For example, I would take a DLO dimension in the width and add 3/4" to it to get the glass width. The same goes for the height. This is all done manually at this point and am looking for a way to automate it. I've tried it with fields and using the dims as the fields, and while it works, it doesn't stack the fractions at all. If you think of a different way to accomplish this, I am more than happy to entertain it. Thanks again!

0 Likes
Message 4 of 10

Kent1Cooper
Consultant
Consultant

How about something like this?

Kent1Cooper_0-1721324570843.png

On the left are two Dimensions [different colors just so you can distinguish], with the 45° text rotation imposed [you can do that in Properties and with some code approaches, though it doesn't seem you can define a Dimension Style to do that], and the "x" as a suffix on the horizontal one, and with their text locations pulled in 45° directions from the middle of it all.  On the right is the same with both extension and both dimension lines suppressed, and in the same color as each other for the one-text-string look.

 

I expect that could be automated, with some kind of ratio of the text height to use for calculating the adjusted text positions.

Kent Cooper, AIA
Message 5 of 10

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

.... I expect that could be automated, with some kind of ratio of the text height to use for calculating the adjusted text positions.


For example, though it doesn't calculate that ratio yet, this:

(defun C:DIMRECT45 (/ ss n pl v1 v2 v3 v4 mid)
  (if (setq ss (ssget "_:L" '((0 . "LWPOLYLINE") (90 . 4) (-4 . "&") (70 . 1))))
    ; only closed, 4-sided LWPolylines on un-locked Layers
    (repeat (setq n (sslength ss)); then -- step through
      (setq
        pl (ssname ss (setq n (1- n)))
        v1 (vlax-curve-getStartPoint pl)
        v2 (vlax-curve-getPointAtParam pl 1)
        v3 (vlax-curve-getPointAtParam pl 2)
        v4 (vlax-curve-getPointAtParam pl 3)
      ); setq
      (if
        (and ; rectangular?
          (equal ; all straight-line segments [no non-zero bulge factors]
            (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 42)) (entget pl)))
            '(0.0 0.0 0.0 0.0)
          ); equal
          (equal (distance v1 v2) (distance v3 v4) 1e-3); 1st & 3rd sides equal lengths
          (equal (distance v2 v3) (distance v1 v4) 1e-3); 2nd & 4th sides equal lengths
          (equal (distance v1 v3) (distance v2 v4) 1e-3); diagonals equal lengths
        ); and
        (progn ; then
          (setq mid (mapcar '/ (mapcar '+ v1 v3) '(2 2)))
          (command "_.dimhorizontal" v1 v3 "_non" (polar mid (* pi 1.25) 2))
          (setpropertyvalue (entlast) "TextPosition" (getvar 'lastpoint)); shift
          (setpropertyvalue (entlast) "TextRotation" (/ pi 4))
          (setpropertyvalue (entlast) "DimensionText" "<> x")
          (command "_.dimvertical" v1 v3 "_non" (polar mid (/ pi 4) 3))
          (setpropertyvalue (entlast) "TextPosition" (getvar 'lastpoint))
          (setpropertyvalue (entlast) "TextRotation" (/ pi 4))
        ); progn
      ); if
    ); repeat
  ); if
  (prin1)
)

did this:

Kent1Cooper_0-1721330531024.png

The amounts of displacement from the middle for each text position [the last numbers in the (polar) functions in the Dimensioning command lines] are just what made for a good-looking result in this situation -- they really need to be calculated based somehow on the length of the text content of each, in relation to the text size in the Dimension Style.  I could try to work that out, if this looks promising for you.  I would need to know your typical Dimension text height at the typical sizes and intended scale of the ones you usually draw.

 

It will let you select, but will not draw Dimensions in, a 4-vertex closed Polyline that is not a rectangle.  It doesn't yet, but should also be made to, check that the orientation is orthogonal, or Dimension values will be skewed.  But [you may have no need for this] it could be made to work with non-orthogonal ones, using Aligned Dimensions along edges, rather than Horizontal/Vertical ones between opposite corners.

Kent Cooper, AIA
Message 6 of 10

cclinton
Contributor
Contributor

Again, thank you for all your help and efforts. Your method might be able to work based on what you've done. I've attached a drawing to show what I am looking for. Alternatively, instead of using the dimension, the user could be prompted to select the two points that define the rectangle, then add the correct size to it. Thank you.

0 Likes
Message 7 of 10

Kent1Cooper
Consultant
Consultant

So you don't actually have an object at the right size to Dimension....

 

I would think a routine could be written to do something like this:

Ask the User to pick inside the DLO area [would not require two points, if always rectangular and orthogonal];

Use BOUNDARY/BPOLY to make the rectangle of the DLO [assuming the area is empty];

OFFSET that outward by [in your example] 3/8";

Do the Dimensioning approach as in my previous Reply on that resulting rectangle.

 

It could put the rectangles it creates on a non-plotting Layer, and get rid of the first one.  [But I would keep the actual-glass-size one around.]  The Layer wouldn't matter if you have reason to get rid of both.

Kent Cooper, AIA
0 Likes
Message 8 of 10

Sea-Haven
Mentor
Mentor

I sent you a PM regarding a window frame program. You could just draw the frame from scratch, based on user input for the size of the frame. As you know the sizes you can add the answer Kent has provided as say last step, without any interaction as you know all the values.

 

Have a look at video.

 

0 Likes
Message 9 of 10

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

.... I would think a routine could be written to do something like this: ....


Fiddling around with this now and then, I arrived at the attached DimGlass45.lsp routine.  See comments at the top of the file.  Lightly tested.  For use only in orthogonal rectangular areas.

It does this in your sample drawing:

Kent1Cooper_0-1721740557199.png

You just call the command and pick inside the glass area, which should have nothing else inside it.  It uses three Dimensions, the "x" in the middle being a separate one, so that the other two don't have any text override.

 

It uses some approximations for the shift off-middle for the text position of the other two, based on the number of characters [without fraction] and an assumed fraction sort of like another character whose size will vary.  Because there won't always be a fraction, it can get a little over-generous on the offset when there isn't:

Kent1Cooper_1-1721740755480.png

but at least things should never overlap.  Maybe there's a more refined way of working out that positioning, with some deeper analysis of the size of the text content.

 

And it remembers current Layer and Dimension Style settings from when you start, as well as Osnap and command echoing and blips [if you use them] settings, and restores them all after.

Kent Cooper, AIA
0 Likes
Message 10 of 10

Sea-Haven
Mentor
Mentor

This would be 1st step draw a window pane. Needs more like correct layers and some more variables as hard coded a couple. Then add Kents code working out the correct 2 points which appear to be 3/8" outside frame. As I work metric 1st go uses 38.75 for 38 3/4" can add correct conversion for input. More variable values can be added to the dcl by adding to the list.

 

 

 ; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/stacked-fractions-in-a-lisp-routine/td-p/12904940
; draw a window by AlanH July 2024

; Glass size dwg

(defun c:dowindow  ( / len ht ve he bot pt pt1)

(defun do-hors (ptt1 lenpl htpl / ptt2 ptt3 ptt4)
  (setq ptt2 (mapcar '+ ptt1 (list lenpl 0.0 0.0)))
  (setq ptt3 (mapcar '+ ptt2 (list 0.0 htpl 0.0)))
  (setq ptt4 (mapcar '+ ptt3 (list (- lenpl) 0.0 0.0)))
  (command "pline" ptt1 ptt2 ptt3 ptt4 "C")
  (princ)
)

(setq oldsnap (getvar 'osmode))
(setvar 'osmode 0)

(if (not AH:getvalsm)(load "Multi Getvals.lsp"))80
(setq ans (AH:getvalsm (list "Enter values " "Length " 8 7 "40" "height" 8 7 "80" "Ver edge" 8 7 "2" "Hor edge " 8 7 "2" "Bot rail " 8 7 "0.375") ))

(setq len (atof (nth 0 ans))
ht  (atof (nth 1 ans))
ve (atof (nth 2 ans))
He (atof (nth 3 ans))
Bot (atof (nth 4 ans))
)

(setq pt (getpoint "\nPick lower left point "))

(setq pt1 (mapcar '+ pt (list (- ve) (- he))))
(setq ht1 (+ (* 2 ve) ht))
(do-hors pt1 he ht1)

(setq pt1 (mapcar '+ pt (list 0 (- he))))
(do-hors pt1 len he)

(setq pt1 (mapcar '+ pt (list len (- he) 0.0)))
(setq ht1 (+ (* 2 ve) ht))
(do-hors pt1 ve ht1)

(setq pt1 (mapcar '+ pt (list 0.0 ht 0.0)))
(do-hors pt1 len he)

(setq pt1 (mapcar '+ pt (list (- (+  0.0625 ve)) (- (+  he 0.375)) 0.0 )))
(do-hors pt1 (+ len (* 2. ve) (* 2. 0.0625)) 0.375)

(setq pt1 (mapcar '+ pt (list (- (+  0.375 ve)) (- (+  he 0.25 0.375)) 0.0 )))
(do-hors pt1 (+ len (* 2. ve) (* 2. 0.375)) (+ ht (* 2. he) 0.25 0.0625 0.437))

(princ)

)

 

SeaHaven_0-1722053263343.png

 

0 Likes