UCS Import

Discussion in 'AutoCAD' started by David Kozina, Oct 23, 2004.

  1. David Kozina

    David Kozina Guest

    When I was using version 2002, Tony Tanzillo had a nice utility available to
    import named UCSs from other drawings. I haven't needed this ability for
    awhile, but I'd sure like to have that ability again. Unfortunately, the
    program doesn't work in 2004 (An alert box says simply "Unable to Connect to
    AutoCAD 2000")

    So, I was wondering if any one or more of the following might be true:
    - Tony has an updated version that works in 2004+?
    - AcadX can do this? (I KNOW it's been discontinued, but I have it and I'm
    curious...)
    - Such a thing may be possible using Object DBX?
    - Someone else may know how to do this and would be willing to give some
    tips?

    Any assistance would be appreciated.

    Best regards,
    David Kozina
     
    David Kozina, Oct 23, 2004
    #1
  2. David - Importing UCSs is fairly easy with ObjectDBX alone, no need for
    AcadX.

    If you search google you should find a number of examples of importing
    other objects like views. They can be easily adapted to import UCSs.
     
    Tony Tanzillo, Oct 25, 2004
    #2
  3. David Kozina

    David Kozina Guest

    Yeeee-haaa!

    <code>

    ; Import UCSs from selected external drawing
    ; thanks to Jeff Mishler for basic function structure
    ; and http://www.visuallisp-tutorial.mapcar.net/importviews.html coders
    ; for 'CopyObjects function usage and (collection->array utility function
    (defun C:ImportUCSs
    (/
    DBX_obj ; DBX Object
    SourceFileName_str ; Source File Name String with path
    SourceFileIsOpen ; Flag: nil- proceed, T- alert user to close source
    file.
    ; /
    ; vl:T
    ; *djkAcadObject*
    ; *djkUserCoordinateSystems*
    ; (djkGetDBXObject
    ; (collection->array
    )
    (setq SourceFileName_str
    (dos_dwgpreview
    "Select drawing to import UCSs."
    (getvar "DWGPREFIX")
    )
    );_end setq

    ; **** Check if source file is open
    (vlax-for OpenDocument (vlax-get-property *djkAcadObject* 'Documents)
    (if (= (vlax-get-property OpenDocument 'Fullname) SourceFileName_str)
    ; then
    (setq SourceFileIsOpen T)
    ; else
    ;
    );_end if
    )
    (if
    (and
    (not SourceFileIsOpen)
    (findfile SourceFileName_str)
    );_end and
    ; then
    (progn
    (setq DBX_obj
    (djkGetDBXObject)
    );_end setq

    ; "open" source for our use...
    (vlax-invoke-method
    DBX_obj
    'Open
    SourceFileName_str
    )

    ; do your stuff here
    ; no selection sets allowed in ObjectDBX
    (vlax-invoke-method
    DBX_obj
    'CopyObjects
    (collection->array
    (vlax-get-property DBX_obj 'UserCoordinateSystems)
    )
    *djkUserCoordinateSystems*
    )

    ; we're done with it
    (vlax-release-object DBX_obj)
    );_end progn
    ; else
    (progn
    (if SourceFileIsOpen
    ; then
    (princ "\nYou tried to use a file in use by Autocad, please close it
    and try again....")
    ; else
    (princ "\nSource file not found, please try again....")
    );_end if
    );_end progn
    );_end if
    ; exit quietly
    (princ)
    );_end defun


    (defun collection->array
    (collection_obj
    /
    array
    i
    )
    (setq array
    (vlax-make-safearray vlax-vbObject
    (cons 0
    (1- (vlax-get-property collection_obj 'Count))
    )
    )
    )
    (setq i 0)
    (vlax-for item collection_obj
    (vlax-safearray-put-element array i item)
    (setq i (1+ i))
    )
    array
    )


    <\code>
     
    David Kozina, Oct 25, 2004
    #3
  4. David Kozina

    Joe Burke Guest

    David,

    An exmple of using the documents collection if source file is open. See the second
    function, DocAtPath.

    Joe Burke

    ;; import named user coordinate systems from selected source file
    (defun c:ImportCoordSys (/ UCSs fullpath srcdoc srcucss cnt name ucslst)
    (setq UCSs
    (vla-get-UserCoordinateSystems
    (vla-get-activedocument (vlax-get-acad-object))))
    (and
    (setq fullpath (getfiled "Source File" (getvar "dwgprefix") "dwg" 0))
    (setq srcdoc (DocAtPath fullpath))
    (setq srcucss (vla-get-UserCoordinateSystems srcdoc))
    (< 0 (vlax-get srcucss 'Count))
    (setq cnt 0)
    (vlax-for x srcucss
    (setq name (vlax-get x 'Name))
    (if
    (and
    (not (tblsearch "ucs" name))
    (not (wcmatch name "_Active*"))
    )
    (setq ucslst (cons x ucslst)
    cnt (1+ cnt)
    )
    )
    )
    (not (vlax-invoke srcdoc 'copyobjects ucslst UCSs))
    (princ (strcat "\nNumber of coordinate systems imported: " (itoa cnt)))
    ) ;and
    (if srcdoc (vlax-release-object srcdoc))
    (princ)
    ) ;end

    ;; return an open document or ODBX doc
    ;; argument: full path
    (defun DocAtPath ( path / *acad* documents srcdoc )
    (setq *acad* (vlax-get-acad-object)
    documents (vla-get-documents *acad*)
    )
    ;check the documents collection
    (vlax-for x documents
    (if (= path (vlax-get x 'FullName))
    (setq srcdoc x)
    )
    )
    ;if not in documents collection, use ObjectDBX
    (if (null srcdoc)
    (cond
    ((> (atoi (getvar "AcadVer")) 15)
    (setq srcdoc (vla-GetInterfaceObject *acad* "ObjectDBX.AxDbDocument.16"))
    (vla-open srcdoc path) ;returns nil
    )
    (T
    (if (not (vl-registry-read
    "HKEY_CLASSES_ROOT\\ObjectDBX.AxDbDocument\\CLSID"))
    (startapp "regsvr32.exe" (strcat "/s \"" (findfile "axdb15.dll") "\""))
    ) ;if
    (setq srcdoc (vla-GetInterfaceObject *acad* "ObjectDBX.AxDbDocument"))
    (vla-open srcdoc path)
    )
    )
    ) ;if
    srcdoc
    ) ;end
     
    Joe Burke, Oct 26, 2004
    #4
  5. Sorry Joe, but you asked for this.

    Where on earth did you get the idea that registering
    AxDb15.dll is something that should be done this way?

    More specifically, your code reads the registry every
    single time it needs to create an AxDbDocument.

    Por que?

    Just check it at load time, and either register it if it's not
    or throw an error.

    I apologize for the lambasting, but when you go into the
    business of posting example code for the benefit of others,
    that code then becomes a legitimate target.
     
    Tony Tanzillo, Oct 26, 2004
    #5
  6. This should help to clarify the goal of avoiding
    redundunant runtime tests that can easily be
    done once at load time, or in the case of this
    polymorphic function, only on the first call. It
    eliminates the runtime testing of the AutoCAD
    version and the need to register AxDb15.dll,
    borrowing some of the code from your post.

    (coded on the fly and untested)

    (defun NewAxDbDocument ()

    (if (> (itoa (getvar "AcadVer")) 15)

    (defun NewAxDbDocument ()
    (vla-getInterfaceObject
    (vlax-get-acad-object)
    "ObjectDBX.AxDbDocument.16"
    )
    )

    (progn
    (defun NewAxDbDocument ()
    (vla-getInterfaceObject
    (vlax-get-acad-object)
    "ObjectDBX.AxDbDocument.16"
    )
    )
    (if (not (vl-registry-read
    "HKEY_CLASSES_ROOT\\ObjectDBX.AxDbDocument\\CLSID"))
    (startapp "regsvr32.exe"
    (strcat "/s \"" (findfile "axdb15.dll") "\"")
    )
    )
    )
    )
    (NewAxDbDocument)
    )
     
    Tony Tanzillo, Oct 26, 2004
    #6
  7. Like I said, coded on the fly and untested.

    The second ProgID ("ObjectDBX.AxDbDocument.16")
    should not have the ".16" suffix.
     
    Tony Tanzillo, Oct 26, 2004
    #7
  8. David Kozina

    Joe Burke Guest

    Tony,

    Thank you for your comments.

    I'll have to study what you said, before I can reply specifically. All I can say at
    this point is the code structure presented was based on something I found in the NG.
    Which in turn may have been based on your example of registering ObjectDBX ActiveX
    services under pre-2004 versions. As demonstrated in BGREP.lsp.

    BTW, no need to worry about offending me. I appreciate the fact code which poses as
    an example, deserves critical examination. Likewise, any mistake which gets your
    attention, probably benefits everyone here.

    Joe Burke
     
    Joe Burke, Oct 26, 2004
    #8
  9. David Kozina

    David Kozina Guest

    Joe and Tony,

    Thank you both for the additional tips/suggestions.
    I won't say I understand them yet, but I see the value and intent.

    I must say I was pretty pleased just to get this thing working in the first
    place! :)
    Further improvements will just be icing on the cake!

    Best regards,
    David Kozina
     
    David Kozina, Oct 26, 2004
    #9
  10. Ok Tony, I promised that I wouldn't take low blows with you anymore so know
    up front that this isn't personal. I'd say the same thing if God himself
    posted this code. I don't like it.

    Polymorphism is great in an environment that breaks up the polymorphic code
    into separate classes and procedures, but a function that redefines itself
    on the fly is a safe harbor for nasty bugs to find a home and hide from the
    unsuspecting programmer.
     
    Bobby C. Jones, Oct 26, 2004
    #10
  11. David Kozina

    Doug Broad Guest

    Hi Bobby,

    I'd have to agree with Tony here. The code is relatively straightforward.
    In addition there aren't a whole lot of places for bugs to hide.

    I would add one thing: The need to ever run regsrv32.exe is only
    once *ever* for a particular installation. It would also be nice to
    just have those kinds of housekeeping tasks done by a separate
    installation batch file.

    There is also a case to be made for version specific code instead
    of making the code do the adaptation work on loading. Obviously,
    Autodesk doesn't try to make its 2004 modules run 2000 code.
    Maybe in trying to support those who aren't keeping up, we make
    life unnecessarily complicated.

    Regards,
    Doug
     
    Doug Broad, Oct 27, 2004
    #11
  12. Hey Doug,
    Thanks for the thoughts. I was hoping someone with more brains than I would
    poke their head in here.

    For someone not on their toes even a simple typo like the one that Tony
    pointed out could potentially take multiple runs of the debugger to catch if
    someone where solely relying on the debugger to catch errors, which I agree
    is bad too. Now imagine a function that creates a difficult logical bug,
    like an off by one error in the portion of the procedure that is undefined
    by the redefinition of the procedure. Someone without the experience of you
    or Tony could enter into an infinite debugger loop and starve to death at
    the keyboard before figuring it out. And even beyond that, it's just not
    straightforward. It's using a trick of the language that not all
    programmers are going to know about.

    I'd much rather see code like this in LISP

    (defun NewAxDbDocument ()
    (if (not (ObjectDbxIsRegistered))
    (RegisterObjectDbx)
    )

    ...code to return AxDbDocument...

    )

    I think that this is easier to understand for programmers of any level.

    So are you making it out to AU this year?
     
    Bobby C. Jones, Oct 27, 2004
    #12
  13. David Kozina

    Doug Broad Guest

    Hi again,

    See comments below:

    Hey, you're the one with the witty reparte and the brilliant prose. And you've
    been gone too long. Its time the newsgroup saw your humorous side more
    often.
    Seems even the simplest functions take me too long to spot the bugs these days. ;-)
    But its a good trick and one of the best features of LISP in contrast to
    compiled code. The code also seemed perspicuous. ;-)

    The flaw of that approach is that (even though it is easy to
    read) it requires that the program check each and every time that
    objectdbx is registered. This seems an unreasonable overhead to
    look pretty. At least with Joe's code, the version check avoids
    the registration check for 2004 and above. Its only with 2000-2002
    that the program needed to be registered. Remember again that it
    only needs to be registered *once*, not even on every load.

    It also hides the really dirty part of implementing the
    ObjectDbxIsRegistered code and the RegisterObjectDbx
    code, which could still be awful.

    Fraid not. Would love to meet everyone. Take care of Robert
    for me. Be sure to challenge him to a game of wheelchair
    basketball. ;-)

    Doug
     
    Doug Broad, Oct 27, 2004
    #13
  14. Hey, you're the one with the witty reparte and the brilliant prose. And
    you've
    More like ditsy and inept! I'm trying to get around more, but I barely have
    the time to lurk much less participate lately.
    days. ;-)

    I feel your pain :)
    You're right. I guess that maybe it's just LISP that I don't care for so
    much anymore. It's not so perspicuous to my foggy brain these days :-\
    Only one flaw in my code, hey, I'm giving myself a raise!
    I do agree that registering an ActiveX server is probably not something you
    want to worry about every time that you run a procedure, as long as you've
    handled it at some point. My little procedure gets even better if you
    remove the check :)

    (defun NewAxDbDocument ()

    ...code to return AxDbDocument...

    )
    I spend a lot of my coding time these days hiding the dirty and the ugly
    with the obvious and the pretty. My current favorite quote, I like quotes,
    pertaining to this is by Martin Fowler, "Any fool can write code that a
    computer can understand. Good programmers write code that humans can
    understand."

    One of the most important aspects to accomplishing this is to separate the
    important code from the distracting code. An easy way to do this is to pull
    all of the distracting code into a well named procedure. It's just like
    using shampoo; wash, rinse, and repeat as needed unitl even the most
    confusing code is reduced to something anyone can understand.

    Anyway, I'm starting to feel like the alter boy preaching to the choir :-\
    I know that you guys know all of this and much much more.
    Will do, and I'll be sure and post the score to let you all know how bad I
    stomped him :)
     
    Bobby C. Jones, Oct 27, 2004
    #14
  15. Sorry Joe. Didn't mean to come off that way, and you are
    absolutely correct about my use of the same pattern In the
    BGREP and other samples, although in that case, the call
    was in the top level command function, rather than in a
    generic library function. One problem with having the test
    in a library function (aside from being redundant), is that in
    the event that it failed to register AxDb15.dll, it doesn't have
    any means of conveying that to its caller, and fails to display
    any kind of error to that effect.

    In my actual production code, I register AxDb15.dll at load-time,
    and display an error if it fails.
     
    Tony Tanzillo, Oct 27, 2004
    #15
  16. You're confusing Polymorphism in OOP with what is at
    its essence, nothing more sinister or complicated than
    the LISP equivalent to C++ preprocessor macros:

    #ifdef R15
    void foo()
    {
    print("This is R15!");
    }
    #else
    void foo()
    {
    print("This is not R15!");
    }
    #endif

    I routinely use something like the above, in C++ code that's
    used on both R15 and R16, but must act differently depending
    on which it runs under. Would it make sense to do a runtime-
    test for which platform you're running on when the compiled code
    can run on only one of the two platforms? In the case of the
    LISP equivalent that I posted, because the code is dynamic,
    so is the conditional definition.

    So, I think we can distill your comments down to their essence,
    which is that any C++ programmer who uses preprocessor macros
    like #define, #ifdef and so on to do conditional code compilation,
    is a dumba$$.
     
    Tony Tanzillo, Oct 27, 2004
    #16
  17. So, I think we can distill your comments down to their essence,
    I think you misunderstand me Tony. This code is quit clear. I can read
    this and easily see the exact intent.
    But a LISP procedure that redefines itself is not clear. The only clue that
    it is redefining itself is a nested defun. And that can easily be missed.
     
    Bobby C. Jones, Oct 27, 2004
    #17
  18. But a LISP procedure that redefines itself is not clear.

    To a competent; skilled programmer, it is perfectly clear.
     
    Tony Tanzillo, Oct 27, 2004
    #18
  19. Aha! We're making headway. I agree completely. I consider myself, and I'm
    sure you'll agree, neither competent nor skilled at catching this type of
    thing when reading through code. If the code isn't blatantly obvious, then
    it's *whoosh* right over my head.
     
    Bobby C. Jones, Oct 27, 2004
    #19
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.