Jump to content

Function to calculate Mtext Justification based on Rotation


Recommended Posts

Posted

Hi,

This might have been resolved before. But has anyone wrote a lisp or function that calculates the text anchor point based on the rotation of the text?

Currently I have a lisp that will prompt the user to select FFL and then will calculate 150mm drop and prompt the user to select point to insert the text and second point to specify angle. I want to push it a step further and add a function to calculate the correct text anchor point which this should be done using the angle (i.e. if pt1X > pt2X & pt1Y>pt2Y then MtextJustify=BottomLeft).

I appreciate that when Angle is 0 or 180 the justification in regards to Top & Bottom (Ignoring Left or Right) cannot be calculate due to the angle being zero, which I dont mind.

 

See Lisp code below

(defun c:LE-CalExtFFL (/ ffl-ent ffl-obj ffl-text ffl-value new-level pt-list pt user-input)
  ;;Set Layer
  (command "_layer" "_m" "-LE-E-External Levels" "")
  
  ;; Function to extract numeric value from FFL text
  (defun extract-ffl-value (text-string / clean-text)
    ;; Remove first 5 characters from the string
    (if (> (strlen text-string) 5)
      (setq clean-text (substr text-string 6))
      (setq clean-text text-string)
    )
    ;; Extract the numeric value
    (if (numberp (read clean-text))
      (read clean-text)
      (progn
        (princ "\nError: Could not extract numeric value from FFL text.")
        nil
      )
    )
  )
  
  ;; Function to create MText at specified point
  (defun create-level-mtext (point level-value rot / mtext-obj)
    ;Calculate Attachment Point based on rotation
    


    ;Place Text
    (setq mtext-obj 
      (entmakex 
        (list
          (cons 0 "MTEXT")
          (cons 100 "AcDbEntity")
          (cons 8 (getvar "CLAYER"))  ; Current layer
          (cons 100 "AcDbMText")
          (cons 10 point)             ; Insertion point
          (cons 40 0.5)               ; Text height (adjust as needed)
          (cons 41 0.0)               ; Reference rectangle width
          (cons 71 1)                 ; Attachment point (top left)
          (cons 72 5)                 ; Drawing direction
          (cons 1 (strcat "+" (rtos level-value 2 3)))  ; Text content with "+" prefix
          (cons 50 rot)               ; Rotation angle
        )
      )
    )
    mtext-obj
  )

  ;;Main program starts here------------------------------------------
  ;; Prompt user to select FFL MText
  (princ "\nSelect the MText containing the FFL (Finished Floor Level): ")
  (setq ffl-ent (car (entsel)))
  ;; Check if a valid MText was selected
  (if (and ffl-ent 
           (= (cdr (assoc 0 (entget ffl-ent))) "MTEXT"))
    (progn
      ;; Get the MText object and extract text content
      (setq ffl-obj (entget ffl-ent))
      (setq ffl-text (cdr (assoc 1 ffl-obj)))
      (princ (strcat "\nFFL Text found: " ffl-text))
      ;; Extract the FFL numeric value
      (setq ffl-value (extract-ffl-value ffl-text))
      (if ffl-value
        (progn
          (setq new-level (- ffl-value 0.15))
          ;; Initialize point list
          (setq pt-list '())
          ;; Prompt for points where to place the new MText
          (princ "\nSelect points where to place the level text (Press Enter to finish): ")
          ;; Loop to collect points
          (while (setq pt (getpoint "\nPick point for level text (or press Enter to finish): "))
            (setq pt-list (append pt-list (list pt)))
            (setq rotation (getangle pt "\nSpecify rotation angle for text (or press Enter for 0 degrees): "))
            (if (not rotation) (setq rotation 0.0))
            
            (create-level-mtext pt new-level rotation)
          )
        )
        (princ "\nCould not extract FFL value from the selected text.")
      )
    )
    (princ "\nError: Please select a valid MText object containing FFL information.")
  )
  (princ) ; Clean exit
)

 

CTS-Example Anchor Point.dwg

Posted (edited)

This would create a text with top left just if the rotation angle is between 0 and 180 else it will be Bottom left.

 

(defun create-level-mtext (pt1 rot / mtext-obj)
  (if (and rot (> rot 0) (< rot pi)) ;check rotation angle
    (setq x 1)
    (Setq x 7)
  )
  (setq mtext-obj
    (entmakex 
      (list
        (cons 0 "MTEXT")
        (cons 100 "AcDbEntity")
        (cons 8 (getvar "CLAYER"))  ; Current layer
        (cons 100 "AcDbMText")
        (cons 10 pt1)               ; Insertion point
        (cons 40 0.5)               ; Text height (adjust as needed)
        (cons 41 0.0)               ; Reference rectangle width
        (cons 71 x)                 ; Attachment point (Top Left)
        (cons 72 5)                 ; Drawing direction
        (cons 1 (strcat "+" (rtos level-value 2 3)))  ; Text content with "+" prefix
        (cons 50 rot)               ; Rotation angle
      )
    )
  )
  mtext-obj
)

 

 

Edited by mhupp
Posted
3 hours ago, mhupp said:

This would create a text with top left just if the rotation angle is between 0 and 180 else it will be Bottom left.

 

(defun create-level-mtext (pt1 rot / mtext-obj)
  (if (and rot (> rot 0) (< rot pi) ;check rotation angle
    (setq x 1)
    (Setq x 7)
  )
  (setq mtext-obj
    (entmakex 
      (list
        (cons 0 "MTEXT")
        (cons 100 "AcDbEntity")
        (cons 8 (getvar "CLAYER"))  ; Current layer
        (cons 100 "AcDbMText")
        (cons 10 pt1)               ; Insertion point
        (cons 40 0.5)               ; Text height (adjust as needed)
        (cons 41 0.0)               ; Reference rectangle width
        (cons 71 x)                 ; Attachment point (Top Left)
        (cons 72 5)                 ; Drawing direction
        (cons 1 (strcat "+" (rtos level-value 2 3)))  ; Text content with "+" prefix
        (cons 50 rot)               ; Rotation angle
      )
    )
  )
  mtext-obj
)

 

 

After you account for '; error: too few arguments:'... Might also consider a single < comparer for limiting this to positive X quadrants, a neither 0 or pi check for all quadrants, etc: 

(if (and rot (< 0 rot pi))                                              ;check rotation angle
  (setq x 1)
  (setq x 7)
)

(if (and rot (/= 0 rot) (/= pi rot))                                    ;check rotation angle
  (setq x 1)
  (setq x 7)
)

(setq x
       (if (and rot (/= 0 rot) (/= pi rot))                             ;check rotation angle
         1
         7
       )
)

 

  • Like 1
Posted

Don't have cad anymore to test this things :( and cant remember if you could throw an if statement inside the entmakex function.

Posted
2 minutes ago, mhupp said:

Don't have cad anymore to test this things :( and cant remember if you could throw an if statement inside the entmakex function.

Sorry to hear that; I didn't know. 

 

Agree it's better to test if you have the data needed before entmake* functions. 

 

If you're wanting to get CAD back, consider joining AUGI as Pro members get a free ADN (Autodesk Developer Network) membership, which would give you any Autodesk product to use for development. 

 

https://www.augi.com/adn-membership-offer

 

Cheers

  • Like 1
Posted

Hi
I'm having trouble reconciling my understanding of your question with what I see in the example drawing.
The square: doesn't it also play a role in determining the text justification?
That is to say: if you select the upper right corner of the square and then specify a horizontal angle to the left, the justification should be bottom right.
However, if you do the same thing starting from the lower right corner of the square, the MTEXT justification should be top right.
Therefore, the idea seems to be that the MTEXT should always be positioned outside the square.

Is this correct?

In this case, the MTEXT angle criterion alone is not sufficient; it's also necessary to consider the object to which it refers.

If all of this is correct, we would need to write a function that analyzes the geometry of the object the MTEXT refers to and determines the justification, taking the angle into account as well.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...