Author Topic: Adding length of Polyline to dia of a circle  (Read 6024 times)

0 Members and 1 Guest are viewing this topic.

Coder

  • Swamp Rat
  • Posts: 827
Adding length of Polyline to dia of a circle
« on: March 18, 2013, 04:49:11 AM »
Hello Everyone .

Is it possible to add the length of the selected polyline to the diameter of a circle into a field by Lisp ?

Thanks in Advance .  :-)

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Adding length of Polyline to dia of a circle
« Reply #1 on: March 18, 2013, 05:29:04 AM »
Yes it's possible. The trick is to generate nested fields inside a formula field.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

fixo

  • Guest
Re: Adding length of Polyline to dia of a circle
« Reply #2 on: March 18, 2013, 05:53:56 AM »
Hi, dude
try this quickly written code
Code: [Select]
(defun c:try(/ acsp adoc alignpt circobj crset cpnt fieldstr mtextobj objid plset)
  (vl-load-com)
(defun get-objectid-x86-x64  (obj / util)
    (setq util (vla-get-utility
(vla-get-activedocument (vlax-get-acad-object))))
    (if (= (type obj) 'ename)
      (setq obj (vlax-ename->vla-object obj))
      ) ;_ end of if
    (if (= (type obj) 'vla-object)
      (if (> (vl-string-search "x64" (getvar "platform")) 0)
(vlax-invoke-method
  util
  "GetObjectIdString"
  obj
  :vlax-false)
(rtos (vla-get-objectid obj) 2 0)
) ;_ end of if
      ) ;_ end of if
    )
(setq adoc (vla-get-activedocument (vlax-get-acad-object)))
  (setq acsp (vla-get-block (vla-get-activelayout adoc)))
  (alert "Select circle first, then polyline")
(if (and (setq crset (ssget"_+.:S:E:L" (list (cons 0  "circle"))))
(setq plset (ssget"_+.:S:E:L" (list (cons 0  "lwpolyline")))))
  (progn
    (setq objId (get-objectid-x86-x64 (vlax-ename->vla-object (ssname plset 0))))
    (setq fieldStr (strcat "%<\\AcObjProp Object(%<\\_ObjId "
      objId
      ">%).Length \\f \"%lu3%pr2\">%"))
    (setq circObj (vlax-ename->vla-object (ssname crset 0)))
    (setq mtextObj (vlax-invoke acsp 'addmtext (setq cpnt (vlax-get circObj 'center)) 0 fieldStr))
    (vlax-put mtextObj 'attachmentpoint 5 )
    (vlax-put mtextObj 'insertionpoint cpnt)
      )
  )
  (princ)
  )

Coder

  • Swamp Rat
  • Posts: 827
Re: Adding length of Polyline to dia of a circle
« Reply #3 on: March 18, 2013, 06:54:19 AM »
Hello ,

I am looking for a code to sum the length of a polyline and diameter of a circle and put them in a field to be changeable ( updated ) when
lengths or diameters of objects were changed .

I am sorry to the confusion .  :oops:

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Adding length of Polyline to dia of a circle
« Reply #4 on: March 18, 2013, 07:20:52 AM »
Combining Fixo's and my ideas. You get the ObjectID's of the PolyLine and the Circle. Then strcat them into the fieldcode of a formula field.

To get the field-codes:
  • Create temporary field, select Objects in the Field Category and Formula in Field Names.
  • Right click in the Formula box, pick Insert Field
  • Select Objects in the Field Category and Object in Field Names.
  • Pick the PL and select its Length property, press OK
  • Type + in the Formula box.
  • Right click in the Formula box, pick Insert Field
  • Select Objects in the Field Category and Object in Field Names.
  • Pick the Circle and select its Diameter property, press OK
Now the formula field-code (at the bottom) should look something like this:
Code: [Select]
%<\AcExpr (%<\_FldPtr 816006576>%+%<\_FldPtr 816002800>%) \f "%lu2%pr2">%Double click on the 1st field inside (the PL's length). It's field code should look something like this:
Code: [Select]
%<\AcObjProp Object(%<\_ObjId 8796087803968>%).Length \f "%lu2%pr8">%Then double click on the 2nd nested field (the Circle's diameter), which gives a field code like this:
Code: [Select]
%<\AcObjProp Object(%<\_ObjId 8796087804096>%).Diameter \f "%lu2%pr8">%
Copy-paste all 3 those into a blank Notepad file. Replace the %<\_FldPtr ######>% portions with their relevant field-codes to get something like this:
Code: [Select]
%<\AcExpr (%<\AcObjProp Object(%<\_ObjId 8796087803968>%).Length \f "%lu2%pr8">%+%<\AcObjProp Object(%<\_ObjId 8796087804096>%).Diameter \f "%lu2%pr8">%) \f "%lu2%pr2">%
Select and copy that line, then go to acad's command line and type this:
Code: [Select]
(progn (prin1 (getstring t)) (princ))Paste the modified field-code and press Enter. Now select the escaped field-code so you can copy and paste it into your lisp. It should be something like this:
Code: [Select]
"%<\\AcExpr (%<\\AcObjProp Object(%<\\_ObjId 8796087803968>%).Length \\f \"%lu2%pr8\">%+%<\\AcObjProp Object(%<\\_ObjId 8796087804096>%).Diameter \\f \"%lu2%pr8\">%) \\f \"%lu2%pr2\">%"
Note as fixo's using the strcat to replace those numbers in the string with the selected ObjectID's do the same for both in the above string.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Coder

  • Swamp Rat
  • Posts: 827
Re: Adding length of Polyline to dia of a circle
« Reply #5 on: March 18, 2013, 07:47:51 AM »
I am really very sorry irneb . :oops:

I can't follow what you have written in general , can't these sequences be done by Lisp ?

Thank you so much for your time and hard work .


irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Adding length of Polyline to dia of a circle
« Reply #6 on: March 18, 2013, 08:03:20 AM »
Yes, that's my point. I'm trying to teach you how to fish, instead of giving you a fish to copy-n-paste.

In order to generate fields you need to set text(like) entities to contain field codes. Unfortunately that is like a new language on its own, but you don't need to learn it since you can make a sample field and then copy its codes. I've should you the method I would go about to get the field-codes so I can write the lisp (which would be nearly 100% the same as fixo's lisp - just the actual field-codes needs to differ).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Coder

  • Swamp Rat
  • Posts: 827
Re: Adding length of Polyline to dia of a circle
« Reply #7 on: March 18, 2013, 09:24:35 AM »
Yes, that's my point. I'm trying to teach you how to fish, instead of giving you a fish to copy-n-paste.

Thank you so much irneb .  :-)

my problem is with the field codes and this is what I can write ...

Code: [Select]
(if (and (setq c (car (entsel "\n Pick circle :")))
         (setq pl (car (entsel "\n Pick polyline :")))
         )
  (progn (setq dia (* (cdr (assoc 40 (entget c))) 2.))
         (setq len (vla-get-length (vlax-ename->vla-object pl)))
         (setq strg (rtos (+ dia len) 2 2))
  )
)

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Adding length of Polyline to dia of a circle
« Reply #8 on: March 18, 2013, 10:05:19 AM »
The thing with field codes is that you need not get the values from lisp. All that you need from the lisp side is the ObjectID, you let the field get the relevant property.

So in your progn you simply need to get the vla-object, then from that you vla-get-ObjectID. Note fixo's code is checking if on a 64 bit system - which means ObjectID is slightly different from the "normal" 32 bit acad.

Then you generate the fieldcode by (using fixo's defun to convert to a string and work with 32/64 bit without worry):
Code - Auto/Visual Lisp: [Select]
  1. (setq cID (get-objectid-x86-x64 (vlax-ename->vla-object c))
  2.       pID (get-objectid-x86-x64 (vlax-ename->vla-object pl)))
  3. (setq fCode (strcat "%<\\AcExpr (%<\\AcObjProp Object(%<\\_ObjId "
  4.                      pID
  5.                      ">%).Length \\f \"%lu2%pr8\">%+%<\\AcObjProp Object(%<\\_ObjId "
  6.                      cID
  7.                      ">%).Diameter \\f \"%lu2%pr8\">%) \\f \"%lu2%pr2\">%"))

And then all that's needed is for you to set a text object's TextString or DXF code 1 to that fieldcode. You can either create a new Text/MText/Block-with-attribute/etc, or you can modify an existing one. The same fieldcode would still be used in the same place.

Note fixo's used the ActiveX way to create a new MText which contains the fieldcode. You can do the same, or you can use entmake if you prefer. Doesn't make any difference to the fieldcode itself.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Coder

  • Swamp Rat
  • Posts: 827
Re: Adding length of Polyline to dia of a circle
« Reply #9 on: March 19, 2013, 12:26:47 AM »
Thank you irneb for the nice work .

The field codes works but at the first creation it will become as field code and I have to double click on the mtext to edit , and it would be ok .
Is there any problem with the code that prevent the field code to be correct from the first creation ?

Many thanks .

Lee Mac

  • Seagull
  • Posts: 12915
  • London, England
Re: Adding length of Polyline to dia of a circle
« Reply #10 on: March 19, 2013, 05:38:23 AM »
A minor suggestion: I would omit the formatting code for the formula operands to ensure that no precision is lost in the calculation, e.g.:
Code - Auto/Visual Lisp: [Select]
  1.     "%<\\AcExpr (%<\\AcObjProp Object(%<\\_ObjId "
  2.     pID
  3.     ">%).Length>% + %<\\AcObjProp Object(%<\\_ObjId "
  4.     cID
  5.     ">%).Diameter>%) \\f \"%lu6%qf1\">%"
  6. )

Coder

  • Swamp Rat
  • Posts: 827
Re: Adding length of Polyline to dia of a circle
« Reply #11 on: March 19, 2013, 06:53:13 AM »
Hi Lee .  :-)

Your modification is also the same result   :-o

Why the code gives that wrong result ?

Code: [Select]
(defun get-objectid-x86-x64 (obj / util)
  (setq util (vla-get-utility (vla-get-activedocument (vlax-get-acad-object))))
  (if (= (type obj) 'ename)
    (setq obj (vlax-ename->vla-object obj))
  ) ;_ end of if
  (if (= (type obj) 'vla-object)
    (if (> (vl-string-search "x64" (getvar "platform")) 0)
      (vlax-invoke-method util "GetObjectIdString" obj :vlax-false)
      (rtos (vla-get-objectid obj) 2 0)
    ) ;_ end of if
  ) ;_ end of if
)

(if (and (setq c (car (entsel "\n Pick circle :"))) (setq pl (car (entsel "\n Pick polyline :"))))
  (entmakex (list (cons 0 "MTEXT")
                  (cons 100 "AcDbEntity")
                  (cons 100 "AcDbMText")
                  (assoc 10 (entget c))
                  (cons 1
                        (strcat "%<\\AcExpr (%<\\AcObjProp Object(%<\\_ObjId "
                                (get-objectid-x86-x64 (vlax-ename->vla-object حم))
                                ">%).Length>% + %<\\AcObjProp Object(%<\\_ObjId "
                                (get-objectid-x86-x64 (vlax-ename->vla-object ؤ))
                                ">%).Diameter>%) \\f \"%lu6%qf1\">%"
                        )
                  )
            )
  )
)
« Last Edit: March 19, 2013, 06:59:15 AM by Coder »

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Adding length of Polyline to dia of a circle
« Reply #12 on: March 19, 2013, 07:11:52 AM »
Probably a good idea Lee.

For some reason nested fields in a formula seems to disregard formatting anyway - it's as if the actual floating point value is used instead of the text displayed. I've even tried to force the issue previously to try and simulate a round off prior to continuing with the rest of the formula, but it has no effect. Fortunately the formula field does include a round function though (but it's undocumented)!

@Coder: There is a slight bug with fields, they don't always display properly as and when they're updated / made through lisp. And once you use nested fields that bug gets worse. What I'd suggest is to call the UpdateField command (similar to some issues I had with my DimArea routine).
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

Lee Mac

  • Seagull
  • Posts: 12915
  • London, England
Re: Adding length of Polyline to dia of a circle
« Reply #13 on: March 19, 2013, 07:20:18 AM »
Why the code gives that wrong result ?

When using entmake to generate Fields, you will also need to entmake the necessary extension dictionaries (see here for an example); for this reason, I always opt for Visual LISP where Fields are concerned, since such dictionaries are generated automatically.

Lee Mac

  • Seagull
  • Posts: 12915
  • London, England
Re: Adding length of Polyline to dia of a circle
« Reply #14 on: March 19, 2013, 07:38:30 AM »
For what its worth, here is how I might write it:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:myfield ( / dia ins len )
  2.     (if
  3.         (and
  4.             (setq len (selectifhasprop "\nSelect Polyline: " "length"))
  5.             (setq dia (selectifhasprop "\nSelect Circle: "   "diameter"))
  6.             (setq ins (getpoint "\nPick Point for MText: "))
  7.         )
  8.         (vla-addmtext
  9.             (vlax-get-property (LM:acdoc) (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace))
  10.             (vlax-3D-point (trans ins 1 0))
  11.             0.0
  12.             (strcat
  13.                 "%<\\AcExpr (%<\\AcObjProp Object(%<\\_ObjId "
  14.                 (LM:ObjectID len)
  15.                 ">%).Length>% + %<\\AcObjProp Object(%<\\_ObjId "
  16.                 (LM:ObjectID dia)
  17.                 ">%).Diameter>%) \\f \"%lu6%qf1\">%"
  18.             )
  19.         )
  20.     )
  21.     (princ)
  22. )
  23.  
  24. (defun selectifhasprop ( msg prp / sel )
  25.     (while
  26.         (progn (setvar 'errno 0) (setq sel (car (nentsel msg)))
  27.             (cond
  28.                 (   (= 7 (getvar 'errno))
  29.                     (princ "\nMissed, try again.")
  30.                 )
  31.                 (   (= 'ename (type sel))
  32.                     (if (not (vlax-property-available-p (setq sel (vlax-ename->vla-object sel)) prp))
  33.                         (princ (strcat "\nObject does not have the " prp " property."))
  34.                     )
  35.                 )
  36.             )
  37.         )
  38.     )
  39.     sel
  40. )
  41.  
  42. ;; ObjectID  -  Lee Mac
  43. ;; Returns a string containing the ObjectID of a supplied VLA-Object
  44. ;; Compatible with 32-bit & 64-bit systems
  45.  
  46. (defun LM:ObjectID ( obj )
  47.     (eval
  48.         (list 'defun 'LM:ObjectID '( obj )
  49.             (if
  50.                 (and
  51.                     (vl-string-search "64" (getenv "PROCESSOR_ARCHITECTURE"))
  52.                     (vlax-method-applicable-p (vla-get-utility (LM:acdoc)) 'getobjectidstring)
  53.                 )
  54.                 (list 'vla-getobjectidstring (vla-get-utility (LM:acdoc)) 'obj ':vlax-false)
  55.                '(itoa (vla-get-objectid obj))
  56.             )
  57.         )
  58.     )
  59.     (LM:ObjectID obj)
  60. )
  61.  
  62. ;; Active Document  -  Lee Mac
  63. ;; Returns the VLA Active Document Object
  64.  
  65. (defun LM:acdoc nil
  66.     (LM:acdoc)
  67. )
  68.