Author Topic: ResultBuffers and LispFunction()  (Read 19379 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
ResultBuffers and LispFunction()
« on: April 04, 2007, 11:32:35 PM »
This is my first sojourn into LispFunction() land

.. surprising, heh !

Testing in AC2008
Anyone see anything blatantly askew about this ?
Code: [Select]
using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;

using System.Text;
using System.IO;

[assembly: CommandClass(typeof(ClassLibrary.kdubClass70405))]

namespace ClassLibrary
{
    /// <summary>
    /// Summary description for kdubClass.
    /// </summary>
    public class kdubClass70405
    {
        public kdubClass70405()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        //
        // From adscodes.h :
        //
        const int RTNONE = 5000; /* No result */
        const int RTREAL = 5001; /*Real number */
        const int RTPOINT = 5002; /* 2D point X and Y only */
        const int RTSHORT = 5003; /* Short integer */
        const int RTANG = 5004; /* Angle */
        const int RTSTR = 5005; /* String */
        const int RTENAME = 5006; /* Entity name */
        const int RTPICKS = 5007; /* Pick set */
        const int RTORINT = 5008; /* Orientation */
        const int RT3DPOINT = 5009; /* 3D point - X, Y, and Z */
        const int RTLONG = 5010; /* Long integer */
        const int RTVOID = 5014; /* Blank symbol */
        const int RTLB = 5016; /* list begin */
        const int RTLE = 5017; /* list end */
        const int RTDOTE = 5018; /* dotted pair */
        const int RTNIL = 5019; /* nil */
        const int RTDXF0 = 5020; /* DXF code 0 for ads_buildlist only */
        const int RTT = 5021; /* T atom */
        const int RTRESBUF = 5023; /* resbuf */
        const int RTMODELESS = 5027; /* interrupted by modeless dialog */

        //
        //
        [LispFunction("TestFolder")]
        public object TestFolder(ResultBuffer buff)
        {
            Array args = buff.AsArray();
            string path = Convert.ToString(((TypedValue)(args.GetValue(0))).Value);
            ResultBuffer resBuff = new ResultBuffer();
            if (File.Exists(path))
            {
                return new TypedValue(RTSTR, "Feed me a FolderName, Dummy !");
            }
            if (!(Directory.Exists(path)))
            {
                return new TypedValue(RTSTR, "Root Folder does not Exist");
            }
            string[] subdirectoryEntries = Directory.GetDirectories(path);
            foreach (string subDirName in subdirectoryEntries)
                resBuff.Add(new TypedValue(
                    RTSTR,
                    subDirName.Substring(subDirName.LastIndexOf("\\") + 1)
                    ));
            if (subdirectoryEntries.Length == 0)
                return new TypedValue(RTSTR, "No Files");
            else
                return resBuff;
        }
    }
}

Code: [Select]
(testfolder "c:\\")
(testfolder "T:\\CONFIG")

(testfolder "c:\\Rubish")
(testfolder "c:\\ACAD2008\\ACAD.EXE")

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #1 on: April 04, 2007, 11:40:03 PM »
Should this:

Code: [Select]
Array args = buff.AsArray();

be this:

Code: [Select]
TypedValue[] tvs = buff.AsArray();

???

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #2 on: April 04, 2007, 11:51:24 PM »
Probably better Glenn :-)
though it did work ..


(testfolder "C:\\CTA17_SteelTools")
(testfolder "T:\\CONFIG")
(testfolder "c:\\Rubish")
(testfolder "c:\\ACAD2008\\ACAD.EXE")
(testfolder "c:\\Program Files\\This is just a Dummy.XML")

("Blocks" "Hotkeys2007" "MenuAndStartup" "Support")
"No Files"
"Root Folder does not Exist"
"Feed me a FolderName, Dummy !"
"Root Folder does not Exist"
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #3 on: April 05, 2007, 12:09:50 AM »
This is easier to read to mine own eyes:
Code: [Select]
[LispFunction("TestFolder")]
public object TestFolder(ResultBuffer buff) {
TypedValue[] args = buff.AsArray();
string path = ((TypedValue)args.GetValue(0)).Value as string;
if(path == null)
return new TypedValue(RTSTR, string.Empty);
ResultBuffer resBuff = new ResultBuffer();
if(File.Exists(path))
return new TypedValue(RTSTR, "Feed me a FolderName, Dummy !");

if(!(Directory.Exists(path)))
return new TypedValue(RTSTR, "Root Folder does not Exist");

string[] subdirectoryEntries = Directory.GetDirectories(path);
if (subdirectoryEntries == null || subdirectoryEntries.Length == 0)
return new TypedValue(RTSTR, "No Files");

foreach(string subDirName in subdirectoryEntries)
resBuff.Add(new TypedValue(
RTSTR,
subDirName.Substring(subDirName.LastIndexOf("\\") + 1)
));

return resBuff;
}

Personal preference is all...

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #4 on: April 05, 2007, 12:28:47 AM »
ahhhhh, the old "do we need the braces" discussion :D

The 'or' conditional IS better ..thanks Glenn
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #5 on: April 05, 2007, 12:35:48 AM »
... and of course, the "No Files" message should be "No Folders"   duh!
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #6 on: April 05, 2007, 12:40:01 AM »
Braces, schmaces :)

WRT the OR, the reason I do this is defensive. I have had some functions in the framework return a valid instance of a return type, even though I would have expected them to return null when they failed. The "IF OR" will use short circuit evaluation - ie It will evaulate the null condition first and if true, bail. It will only move onto the next test if that fails. It then checks the Length in this case. Imagine what would happen if you had a null instance and tried using the Length property? Big fat exception. So the order of the tests is the improtant part.

... and of course, the "No Files" message should be "No Folders"   duh!

Yes it should.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #7 on: April 05, 2007, 12:44:00 AM »
...........The "IF OR" will use short circuit evaluation - ............. Big fat exception..............

Yep, I bashed my head on the keyboard when I saw your alternative.
... may have picked it up tomorrow when I re-wrote it :-D
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: ResultBuffers and LispFunction()
« Reply #8 on: April 05, 2007, 08:10:51 AM »
Awesome Kerry!

I like to stick the TypedValue struct in a list instead of an array (opinion)

Code: [Select]
List<TypedValue>args= new List<TypedValue>(buff.AsArray());

also have a look at the LispDataType enum

Code: [Select]
resBuff.Add(new TypedValue((int)LispDataType.yourtype , yourvalue));


edit: ps I like the way Kerry's code is layed out better.
« Last Edit: April 05, 2007, 09:12:03 AM by Danielm103 »

TonyT

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #9 on: April 05, 2007, 04:53:08 PM »

Code: [Select]
        //
        // From adscodes.h :
        //
        const int RTNONE = 5000; /* No result */
        const int RTREAL = 5001; /*Real number */
        const int RTPOINT = 5002; /* 2D point X and Y only */
        const int RTSHORT = 5003; /* Short integer */
        const int RTANG = 5004; /* Angle */
        const int RTSTR = 5005; /* String */
        const int RTENAME = 5006; /* Entity name */
        const int RTPICKS = 5007; /* Pick set */

Have a look at the LispDataType enum
« Last Edit: April 05, 2007, 04:54:14 PM by TonyT »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #10 on: April 05, 2007, 09:02:36 PM »

Also, .. is one supposed to use a
Code: [Select]
[assembly: CommandClass(typeof(ClassLibrary.classname))]
on a
Code: [Select]
[LispFunction("function")]?
I do it all the time, I just don't want to explode other peoples computers

I don't know Daniel ... I'll have to do some more reading :-)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #11 on: April 05, 2007, 09:03:40 PM »

Code: [Select]
        //
        // From adscodes.h :
//..............................
 

Have a look at the LispDataType enum

Thanks Tony, I will.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #12 on: April 05, 2007, 09:07:41 PM »
Ahhhhh .. playtime
Code: [Select]
public enum LispDataType
{
    Angle = 0x138c,
    DottedPair = 0x139a,
    Double = 0x1389,
    Int16 = 0x138b,
    Int32 = 0x1392,
    ListBegin = 0x1398,
    ListEnd = 0x1399,
    Nil = 0x139b,
    None = 0x1388,
    ObjectId = 0x138e,
    Orientation = 0x1390,
    Point2d = 0x138a,
    Point3d = 0x1391,
    SelectionSet = 0x138f,
    T_atom = 0x139d,
    Text = 0x138d,
    Void = 0x1396
}
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gilseorin

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #13 on: April 06, 2007, 11:38:28 AM »
I introduce my first LispFuction.

Code: [Select]
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using System.Math;

public class GILSclass1
{
 const int RTREAL = 5001;

 [LispFuction("PolarPoint")]
 public ResultBuffer DotNetfunction(ResultBuffer rbfArgs)
 {
   Array arInputArgs;
   Point3d co;
   double ang;
   double dst;
   arInputArgs = rbfArgs.AsArray;
   co = ((TypedValue)(arInputArgs.GetValue(0))).Value;
   ang = ((TypedValue)(arInputArgs.GetValue(1))).Value;
   dst = ((TypedValue)(arInputArgs.GetValue(2))).Value;
   double x = co.X;
   double y = co.Y;
   double z = co.Z;
   double px = dst * Cos(ang);
   double py = dst * Sin(ang);
   double pz = z;
   double ox = px + x;
   double oy = py + y;
   double oz = pz;
   ResultBuffer rbfResult;
   rbfResult = new ResultBuffer(new TypedValue(System.Convert.ToInt32(5001), ox), _
                                new TypedValue(System.Convert.ToInt32(5001), oy), _
                                new TypedValue(System.Convert.ToInt32(5001), oz));
   return rbfResult;
 }
}

LE

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #14 on: April 06, 2007, 10:59:34 PM »
Ahhhhh .. playtime
Code: [Select]
public enum LispDataType
{
    Angle = 0x138c,
    DottedPair = 0x139a,
    Double = 0x1389,
    Int16 = 0x138b,
    Int32 = 0x1392,
    ListBegin = 0x1398,
    ListEnd = 0x1399,
    Nil = 0x139b,
    None = 0x1388,
    ObjectId = 0x138e,
    Orientation = 0x1390,
    Point2d = 0x138a,
    Point3d = 0x1391,
    SelectionSet = 0x138f,
    T_atom = 0x139d,
    Text = 0x138d,
    Void = 0x1396
}

Are you still playing?

I have time to play a little, one more time in the C# stuff, I tried to complete one my functions I have in C++, and implement what Tony recommended, just the last part still not completed, the dotted pair list output build (I don't need to much lisp functions anymore, but it is always good to know and learn more!).

The arguments requires to be something like: (setq lst (list '("one" 2) '("one" 3) '("two" 4) '("two" 5)))
Command: (summation lst)

First not using LispDataType and not returning a list, just WriteMessage()
Code: [Select]
[LispFunction("Summation")]
static public void summation(ResultBuffer args)
{
    Document doc = acadApp.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    Dictionary<string, short> openWith = new Dictionary<string, short>();
    IEnumerator it = args.GetEnumerator();
    while (it.MoveNext())
    {
        short ad = 0, num = 0;
        TypedValue val = (TypedValue)it.Current;
        // ignore start or end of list
        short RTLB = 5016, RTLE = 5017;
        if (val.TypeCode == RTLB || val.TypeCode == RTLE) { }
        else
        {
            string sKey = val.Value.ToString();
            it.MoveNext();
            val = (TypedValue)it.Current;
            num = (short)val.Value;
            try
            {
                openWith.Add(sKey, num);
            }
            catch (ArgumentException)
            {
                if (openWith.TryGetValue(sKey, out ad))
                {
                    num = (short)(num + ad);
                    openWith.Remove(sKey);
                    openWith.Add(sKey, num);
                }
            }
        }
    }
    foreach (KeyValuePair<string, short> kvp in openWith)
    {
        ed.WriteMessage("\nKey = {0}, Value = {1}",
            kvp.Key, kvp.Value);
    }
}

Next one, trying to implement LispDataType and to return a ResultBuffer
Code: [Select]
[LispFunction("SummationR")]
static public void summationr(ResultBuffer args)
{
    ResultBuffer res = new ResultBuffer();
    Document doc = acadApp.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    Dictionary<string, short> openWith = new Dictionary<string, short>();
    IEnumerator it = args.GetEnumerator();
    while (it.MoveNext())
    {
        short ad = 0, num = 0;
        TypedValue val = (TypedValue)it.Current;
        if ((LispDataType)val.TypeCode != LispDataType.ListBegin && (LispDataType)val.TypeCode != LispDataType.ListEnd)
        {
            string sKey = val.Value.ToString();
            it.MoveNext();
            val = (TypedValue)it.Current;
            num = (short)val.Value;
            try
            {
                openWith.Add(sKey, num);
            }
            catch (ArgumentException)
            {
                if (openWith.TryGetValue(sKey, out ad))
                {
                    num = (short)(num + ad);
                    openWith.Remove(sKey);
                    openWith.Add(sKey, num);
                }
            }
        }
    }
    foreach (KeyValuePair<string, short> kvp in openWith)
    {
        ed.WriteMessage("\nKey = {0}, Value = {1}", kvp.Key, kvp.Value);
        //TypedValue TV = new TypedValue();
        //LispDataType LSPT = new LispDataType.
        //res.Add()
    }
}

Thanks!

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #15 on: April 07, 2007, 03:52:07 AM »
These are the relationships :
Code: [Select]
/*
  LispDataType.Angle        // RTANG        = 5004
  LispDataType.DottedPair   // RTDOTE       = 5018
  LispDataType.Double       // RTREAL       = 5001
  LispDataType.Int16        // RTSHORT      = 5003
  LispDataType.Int32        // RTLONG       = 5010
  LispDataType.ListBegin    // RTLB         = 5016
  LispDataType.ListEnd      // RTLE         = 5017
  LispDataType.Nil          // RTNIL        = 5019
  LispDataType.None         // RTNONE       = 5000
  LispDataType.ObjectId     // RTENAME      = 5006
  LispDataType.Orientation  // RTORINT      = 5008
  LispDataType.Point2d      // RTPOINT      = 5002
  LispDataType.Point3d      // RT3DPOINT    = 5009
  LispDataType.SelectionSet // RTPICKS      = 5007
  LispDataType.T_atom       // RTT          = 5021
  LispDataType.Text         // RTSTR        = 5005
  LispDataType.Void         // RTVOID       = 5014
  */
  //const int RTDXF0        = 5020; /* DXF code 0 for ads_buildlist only */
  //const int RTRESBUF      = 5023; /* resbuf */
  //const int RTMODELESS    = 5027; /* interrupted by modeless dialog */

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #16 on: April 07, 2007, 04:20:15 AM »
a little hack to test ...
The enumerated


Code: [Select]
        [LispFunction("ReturnToMe")]
        static public ResultBuffer ReturnToMe(ResultBuffer args)
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            foreach (TypedValue rbtv in args)
            {
                switch (rbtv.TypeCode)
                {
                    case (Int32)LispDataType.ListBegin:
                        ed.WriteMessage("(");
                        break;
                    case (Int32)LispDataType.ListEnd:
                        ed.WriteMessage(")");
                        break;
                    case (Int32)LispDataType.Text:
                        ed.WriteMessage("\"{0}\"", rbtv.Value);
                        break;
                    case (Int32)LispDataType.T_atom:
                        ed.WriteMessage(" T ");
                        break;
                    case (Int32)LispDataType.Nil:
                        ed.WriteMessage(" nil ");
                        break;
                   
                    default:
                        ed.WriteMessage(" {0} ", rbtv.Value);
                        break;
                }
            }
            return args;
        }
        //


Quote
(ReturnToMe "A" 1 2.3 '(4 . 5) '(6 7 8 ) (= 1 1.0))
;-> ("A" 1 2.3 (4 . 5) (6.0 7.0 8.0 ) T)

(setq testval "Message")
(ReturnToMe (/ 7 8.0)
               (CONS "one" 1)
               (STRCAT testval " goes here.")
               (GETPOINT "Pick a point")
               (ENTSEL)
)

;-> (  0.875
   ("one" . 1)
   "Message goes here."
   (-200.0 5639.93 0.0)
   (<Entity name: 7efb52f0> (-204.739 2994.1 0.0))
)

The obligatory piccy:
« Last Edit: April 07, 2007, 06:38:51 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #17 on: April 07, 2007, 04:29:54 AM »
Just an observation :

the case test in this :
Code: [Select]
                    case (Int32)LispDataType.ListBegin:
                        ed.WriteMessage("(");
                        break;
may seem excessive, but the compiler converts it to it's numeric value , so it's not process intensive
ie
Code: [Select]
            case 0x1398:
                editor.WriteMessage("(");
                break;
and the IDE IntelliSense helps with the syntax :
The obligatory piccy:
« Last Edit: April 07, 2007, 06:38:33 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

LE

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #18 on: April 07, 2007, 12:02:24 PM »
Kerry;

I was talking about on how to build the output list for autolisp, anyway I found it, here is (it is the same criteria when using arx):

Code: [Select]
[LispFunction("SummationR")]
public object summationr(ResultBuffer args)
{
    ResultBuffer res = new ResultBuffer();
    Document doc = acadApp.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    Dictionary<string, short> openWith = new Dictionary<string, short>();
    IEnumerator it = args.GetEnumerator();
    while (it.MoveNext())
    {
        short ad = 0, num = 0;
        TypedValue val = (TypedValue)it.Current;
        if ((LispDataType)val.TypeCode != LispDataType.ListBegin && (LispDataType)val.TypeCode != LispDataType.ListEnd)
        {
            string sKey = val.Value.ToString();
            it.MoveNext();
            val = (TypedValue)it.Current;
            num = (short)val.Value;
            try
            {
                openWith.Add(sKey, num);
            }
            catch (ArgumentException)
            {
                if (openWith.TryGetValue(sKey, out ad))
                {
                    num = (short)(num + ad);
                    openWith.Remove(sKey);
                    openWith.Add(sKey, num);
                }
            }
        }
    }
    res.Add(new TypedValue((int)LispDataType.ListBegin, -1)); // open the main list "("
    foreach (KeyValuePair<string, short> kvp in openWith)
    {
        res.Add(new TypedValue((int)LispDataType.ListBegin, -1)); // open a list "("
        res.Add(new TypedValue((short)LispDataType.Text, kvp.Key)); // add the key "str"
        res.Add(new TypedValue((short)LispDataType.Int16, kvp.Value)); // add the value 'short'
        res.Add(new TypedValue((int)LispDataType.ListEnd, -1)); // close the list ")"
    }
    res.Add(new TypedValue((int)LispDataType.ListEnd, -1)); // close the main list ")"
    return res;
}

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #19 on: April 07, 2007, 06:50:30 PM »
Luis,
Why are you casting the LispDataType enumerator to int in some cases and to short in others ?
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

LE

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #20 on: April 07, 2007, 07:08:57 PM »
Luis,
Why are you casting the LispDataType enumerator to int in some cases and to short in others ?

If I not, I get some errors, that's was the only way to make it work.

I think I understood your question, it is a habit... it can be all (int)'s


Isn't it a pity,
George
« Last Edit: April 07, 2007, 07:20:20 PM by George Harrison »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #21 on: April 07, 2007, 07:23:17 PM »
Are these the Namespaces you are using ?
 
Code: [Select]
           System.Collections.Generic.Dictionary<string, short>
                openWith = new Dictionary<string, short>();
            System.Collections.IEnumerator
                it = args.GetEnumerator();
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

LE

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #22 on: April 07, 2007, 07:25:54 PM »
.. but why  int in some cases and to short in others ?

It's was my habit I checked and can be all the casts as (int)

Quote
did this line work for you ?
 IEnumerator it = args.GetEnumerator();

Yes.

Quote
using System;
using Autodesk.AutoCAD.Runtime;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Threading;
using System.Globalization;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcEd = Autodesk.AutoCAD.EditorInput;
using AcGe = Autodesk.AutoCAD.Geometry;
using AcRx = Autodesk.AutoCAD.Runtime;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcWd = Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.LayerManager;
using System.Collections;
using AddTicks17;

[assembly: CommandClass(typeof(ClassLibrary.LESQClass))]
...


Isn't it a pity,
George

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #23 on: April 07, 2007, 07:42:10 PM »
(("one" 5) ("two" 9))


what's with the "Isn't it a pity" ?
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

LE

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #24 on: April 07, 2007, 07:46:21 PM »
what's with the "Isn't it a pity" ?

Hey... that's the name of one of my songs  :laugh:

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #25 on: April 07, 2007, 08:49:58 PM »
For the spectators ..

The TypedValue structure holds 2 private properties
m_typeCode which is a short .. [Int16]
m_value which is an object

one of the constructors for the TypedValue struct is built like this :
Code: [Select]
public TypedValue(int typeCode, object value)
{
    this.m_typeCode = (short) typeCode;
    this.m_value = value;
}
... which accepts arguments of type  int [Int32] and object respectively.

The public accessor  to the internal m_typeCode returns a short [Int16]

The compiler will allow implicit type conversion from lower to higher,
so passing a short where an int is expected is generally accepted.

.. so, while the constructor is defined as:
(new TypedValue((int)LispDataType.Text, kvp.Key))
the comliler will allow
(new TypedValue((short)LispDataType.Text, kvp.Key))


BTW.
The (int) in front of (int)LispDataType... is called a cast. It is casting (converting) the type to int in this case, ensuring type integrity.

also BTW.
The  LispDataType.Text enumerator always evaluates to a numeric value of 5005
so we could have used
(new TypedValue(5005, kvp.Key))


Int16 has a MaxValue = 32767
Int32 has a MaxValue = 2147483647




« Last Edit: April 07, 2007, 08:56:04 PM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

LE

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #26 on: April 07, 2007, 09:22:32 PM »
Kerry;

My idea/intention was just to use LispDataType as was mentioned here.


 :-)
Beware of darkness
« Last Edit: April 09, 2007, 09:56:16 AM by le »

TonyT

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #27 on: April 07, 2007, 11:23:37 PM »
You can use constants or LispDataType as each makes
the code more explicit than using 0xNNNN....

Code: [Select]

           Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            foreach (TypedValue rbtv in args)
            {
                switch (rbtv.TypeCode)
                {
                    case (Int32)LispDataType.ListBegin:
                        ed.WriteMessage("(");
                        break;
                    case (Int32)LispDataType.ListEnd:
                        ed.WriteMessage(")");
                        break;

                       ........

could have also been done thusly:

           Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            foreach (TypedValue rbtv in args)
            {
                switch ((LispDataType) rbtv.TypeCode)    /////////<- just cast this
                {
                    case LispDataType.ListBegin:        ///// rather than each of these
                        ed.WriteMessage("(");
                        break;
                    case LispDataType.ListEnd:
                        ed.WriteMessage(")");
                        break;



Just an observation :

the case test in this :
Code: [Select]
                    case (Int32)LispDataType.ListBegin:
                        ed.WriteMessage("(");
                        break;
may seem excessive, but the compiler converts it to it's numeric value , so it's not process intensive
ie
Code: [Select]
            case 0x1398:
                editor.WriteMessage("(");
                break;
and the IDE IntelliSense helps with the syntax :
The obligatory piccy:

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #28 on: April 07, 2007, 11:49:58 PM »
                       ........
// could have also been done thusly:
                 switch ((LispDataType) rbtv.TypeCode)    /////////<- just cast this

Yep, I'd made those changes this morning .. fresh light and fresh coffee .. ;-)

Thanks Tony.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #29 on: April 07, 2007, 11:54:29 PM »
I introduce my first LispFuction.

Code: [Select]
........
 [LispFuction("PolarPoint")]
 public ResultBuffer DotNetfunction(ResultBuffer rbfArgs)
 {
 ..............}

gilseorin,
how about something like this ?
Code: [Select]
        // (PolarPoint '(0.0 0.0 0.0) 0.2617993877 1000.0)
        [LispFunction("PolarPoint")]
        public ResultBuffer DotNetPolarPoint(ResultBuffer rbfArgs)
        {
            TypedValue[] arInputArgs = rbfArgs.AsArray();
            Point3d co = (Point3d)((TypedValue)(arInputArgs.GetValue(0))).Value;
            double ang = (double)((TypedValue)(arInputArgs.GetValue(1))).Value;
            double dst = (double)((TypedValue)(arInputArgs.GetValue(2))).Value;

            ResultBuffer rbfResult =
                new ResultBuffer(
                    new TypedValue((int)LispDataType.Point3d,               
                        new Point3d(co.X + dst * System.Math.Cos(ang),
                                    co.Y + dst * System.Math.Sin(ang),
                                    co.Z)));
            return rbfResult;
        }

added:duh!
co.Z was  co.Y
made it a bit too upendicular :-)
« Last Edit: April 08, 2007, 12:08:56 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gilseorin

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #30 on: April 08, 2007, 06:02:53 AM »
Sweet and cool!
Thank you for enlarging my knowledge,Kerry.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: ResultBuffers and LispFunction()
« Reply #31 on: April 09, 2007, 09:36:16 AM »
How about using TonyT’s awesome TypedValueList class ?
http://www.theswamp.org/index.php?topic=14495.msg186823#msg186823

Code: [Select]
[LispFunction("PolarPoint")]
    public ResultBuffer DotNetPolarPoint(ResultBuffer rbfArgs)
    {
      //TonyT's cool TypedValueList
      TypedValueList arInputArgs = new TypedValueList(rbfArgs.AsArray());
      TypedValueList arOutputArgs = new TypedValueList();
      //
      Point3d co = (Point3d)arInputArgs[0].Value;
      double ang = (double)arInputArgs[1].Value;
      double dst = (double)arInputArgs[2].Value;
      //
      arOutputArgs.Add((int)LispDataType.Point3d,
                       new Point3d(co.X +
                       (dst * Math.Cos(ang)),
                       co.Y + (dst * Math.Sin(ang)),
                       co.Z));

      return arOutputArgs; //edit
    }

This seems to be the way to go, thanks Tony
« Last Edit: April 09, 2007, 11:20:57 AM by Danielm103 »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: ResultBuffers and LispFunction()
« Reply #32 on: April 09, 2007, 09:43:16 AM »
I KNEW I'd seen something like that somewhere ... and couldn't remeber where ... and it was in our own garden all the time .. thanks Dan and Tony.
 
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gilseorin

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #33 on: April 09, 2007, 10:42:51 AM »
Another new awesome  skill!
Thank you so much, Danielm103.


TonyT

  • Guest
Re: ResultBuffers and LispFunction()
« Reply #34 on: April 10, 2007, 06:07:13 AM »

Thanks Dan. I posted a stripped down version of that class
because the remainder was dependent on other things that
would needed to have come along for the ride.

One thing you might note is that the class has implicit
conversions to/from ResultBuffer, TypedValue[], and
SelectionFilter.

That means that instead of:

Code: [Select]

TypedValueList arInputArgs = new TypedValueList(rbfArgs.AsArray());


You can just do:

Code: [Select]

TypedValueList arInputArgs = new TypedValueList(rbfArgs);

// Or for that matter, you can just do this:

TypedValueList arInputArgs = rbfArgs;

// Just to make that clearer:

   DBObject myObj = myTrans.GetObject(...);

   TypedValueList list = myObj.XData;  // assign directly to TypedValueList

   // modify list here

   myObj.XData = list;     // implicitly convert to a ResultBuffer




Also, on the typecasting from DxfCode and LispDataType,
business, you can also clean up code that uses that class,
by adding a few overloaded Add methods, like so:

Code: [Select]

    public void Add(LispDataType type, object value)
    {
        Add( new TypedValue((int) type, value));
    }

    public void Add(DxfCode code, object value)
    {
        Add( new TypedValue((int) code, value));
    }


That means, you can add items to the list, more easily
and cleanly, at a slight cost:

Code: [Select]

     TypedValueList list = new TypedValueList();

     list.Add( LispDataType.ListBegin, 0 );
     list.Add( LispDataType.Double, 99.000 );
     list.Add( LispDataType.String, "hello world" );
     list.Add( LispDataType.ListEnd, 0 );


With those two overloads, there's no need to create
TypedValues to add items to the list, or typecast from
either DxfCode or LispDataType.

Lastly, another improvement is to overload the constructor
to take IEnumerable arguments, which allows you to create
a new instance that's populated from any type that can
enumerate TypedValues (e.g. ResultBuffer, TypedValue[],
ArrayList, List<TypedValue>, or another TypedValueList):

Code: [Select]

   public TypedValueList( IEnumerable<TypedValue> source )
   {
      AddRange( source );
   }

   public TypedValueList( IEnumerable source )
   {
      foreach( TypedValue v in source )
         Add( v );
   }


How about using TonyT’s awesome TypedValueList class ?
http://www.theswamp.org/index.php?topic=14495.msg186823#msg186823

Code: [Select]
[LispFunction("PolarPoint")]
    public ResultBuffer DotNetPolarPoint(ResultBuffer rbfArgs)
    {
      //TonyT's cool TypedValueList
      TypedValueList arInputArgs = new TypedValueList(rbfArgs.AsArray());
      TypedValueList arOutputArgs = new TypedValueList();
      //
      Point3d co = (Point3d)arInputArgs[0].Value;
      double ang = (double)arInputArgs[1].Value;
      double dst = (double)arInputArgs[2].Value;
      //
      arOutputArgs.Add((int)LispDataType.Point3d,
                       new Point3d(co.X +
                       (dst * Math.Cos(ang)),
                       co.Y + (dst * Math.Sin(ang)),
                       co.Z));

      return arOutputArgs; //edit
    }

This seems to be the way to go, thanks Tony

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8691
  • AKA Daniel
Re: ResultBuffers and LispFunction()
« Reply #35 on: April 10, 2007, 07:01:50 AM »
Fantastic! Thanks Tony

Also for those who are watching, this constructor overload might be handy for args like

Code: [Select]
LispDataType.T_atom

LispDataType.Nil

Code: [Select]
public void Add(LispDataType type)
    {
      Add(new TypedValue((int)type));
    }