TheSwamp
Code Red => .NET => Topic started by: Kerry 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 ?
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;
}
}
}
(testfolder "c:\\")
(testfolder "T:\\CONFIG")
(testfolder "c:\\Rubish")
(testfolder "c:\\ACAD2008\\ACAD.EXE")
-
Should this:
Array args = buff.AsArray();
be this:
TypedValue[] tvs = buff.AsArray();
???
-
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"
-
This is easier to read to mine own eyes:
[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...
-
ahhhhh, the old "do we need the braces" discussion :D
The 'or' conditional IS better ..thanks Glenn
-
... and of course, the "No Files" message should be "No Folders" duh!
-
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.
-
...........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
-
Awesome Kerry!
I like to stick the TypedValue struct in a list instead of an array (opinion)
List<TypedValue>args= new List<TypedValue>(buff.AsArray());
also have a look at the LispDataType enum
resBuff.Add(new TypedValue((int)LispDataType.yourtype , yourvalue));
edit: ps I like the way Kerry's code is layed out better.
-
//
// 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
-
Also, .. is one supposed to use a
[assembly: CommandClass(typeof(ClassLibrary.classname))]
on a
[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 :-)
-
//
// From adscodes.h :
//..............................
Have a look at the LispDataType enum
Thanks Tony, I will.
-
Ahhhhh .. playtime
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
}
-
I introduce my first LispFuction.
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;
}
}
-
Ahhhhh .. playtime
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()
[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
[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!
-
These are the relationships :
/*
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 */
-
a little hack to test ...
The enumerated
[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;
}
//
(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:
-
Just an observation :
the case test in this :
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
case 0x1398:
editor.WriteMessage("(");
break;
and the IDE IntelliSense helps with the syntax :
The obligatory piccy:
-
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):
[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;
}
-
Luis,
Why are you casting the LispDataType enumerator to int in some cases and to short in others ?
-
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
-
Are these the Namespaces you are using ?
System.Collections.Generic.Dictionary<string, short>
openWith = new Dictionary<string, short>();
System.Collections.IEnumerator
it = args.GetEnumerator();
-
.. 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)
did this line work for you ?
IEnumerator it = args.GetEnumerator();
Yes.
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
-
(("one" 5) ("two" 9))
what's with the "Isn't it a pity" ?
-
what's with the "Isn't it a pity" ?
Hey... that's the name of one of my songs :laugh:
-
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 :
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
-
Kerry;
My idea/intention was just to use LispDataType as was mentioned here.
:-)
Beware of darkness
-
You can use constants or LispDataType as each makes
the code more explicit than using 0xNNNN....
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 :
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
case 0x1398:
editor.WriteMessage("(");
break;
and the IDE IntelliSense helps with the syntax :
The obligatory piccy:
-
........
// 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.
-
I introduce my first LispFuction.
........
[LispFuction("PolarPoint")]
public ResultBuffer DotNetfunction(ResultBuffer rbfArgs)
{
..............}
gilseorin,
how about something like this ?
// (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 :-)
-
Sweet and cool!
Thank you for enlarging my knowledge,Kerry.
-
How about using TonyT’s awesome TypedValueList class ?
http://www.theswamp.org/index.php?topic=14495.msg186823#msg186823
[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
-
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.
-
Another new awesome skill!
Thank you so much, Danielm103.
-
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:
TypedValueList arInputArgs = new TypedValueList(rbfArgs.AsArray());
You can just do:
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:
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:
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):
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
[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
-
Fantastic! Thanks Tony
Also for those who are watching, this constructor overload might be handy for args like
LispDataType.T_atom
LispDataType.Nil
public void Add(LispDataType type)
{
Add(new TypedValue((int)type));
}