TheSwamp

Code Red => .NET => Topic started by: AARYAN on January 27, 2015, 05:08:04 AM

Title: Position of Point3d in a List
Post by: AARYAN on January 27, 2015, 05:08:04 AM
Hi All,

Need some help.

I am trying to convert the lisp code into c# but unable to pass a list of lists to a lispfunction. Any help would be appreciable.

Code in c# might be funny please bear.

Piece of Code taken from the gettin function written by ymg.
Code - Auto/Visual Lisp: [Select]
  1. (FOREACH tt ll ; ll is list of lists having 3 3dpoints in each list (((500 200 1.1) (600 700 2.3) (800 600 3.3)) ((400 100 4.1) (500 700 2.6) (200 600 3.5)))
  2.  
  3.     (SETQ tls (CONS (LIST (VL-POSITION (CAR tt) pts) ; pts is a list of 3d points (e.g ((500 250 3.1) (400 600 2.2))
  4.  
  5.                                        (VL-POSITION (CADR tt) pts)
  6.  
  7.                                        (VL-POSITION (CADDR tt) pts)) tls)))



Code - C#: [Select]
  1. [LispFunction("GetPositions")]
  2.         public Object GetPositions(ResultBuffer resbuf)
  3.         {
  4.             TypedValue[] args = resbuf.AsArray();
  5.             ResultBuffer retout = new ResultBuffer();
  6.             List<Point3d> PList = new List<Point3d>();
  7.             List<List<Point3d>> TList = new List<List<Point3d>>();
  8.             List<int> XList = new List<int>();
  9.            
  10.             for (int i = 0; i < args.Length - 1; i++)
  11.             {
  12.                 PList.Add((Point3d)args[i].Value);
  13.             }
  14.  
  15.             for (int i = 1; i < args.Length - 1; i++)
  16.             {
  17.                 TList.Add((List<Point3d>)args[i].Value);
  18.             }
  19.  
  20.             for (int i = 0; i < TList.Count; i++)
  21.             {
  22.                 var tr = TList[i];
  23.                 var P1 = tr[0];
  24.                 var P2 = tr[1];
  25.                 var P3 = tr[2];
  26.                 XList.Add(PList.IndexOf(P1));
  27.                 XList.Add(PList.IndexOf(P2));
  28.                 XList.Add(PList.IndexOf(P3));
  29.             }
  30.             retout.Add(new TypedValue((int)LispDataType.ListBegin));
  31.             retout.Add(new TypedValue((int)LispDataType.Point3d, XList));
  32.             retout.Add(new TypedValue((int)LispDataType.ListEnd));
  33.             return retout;
  34.         }

Can anyone please update the c# code to get result as in Lisp.

Regards


edit kdub ==> code formatting tags added
Title: Re: Position of Point3d in a List
Post by: AARYAN on January 27, 2015, 11:55:31 PM
Can anyone at least(please) point out how can it be done?
Title: Re: Position of Point3d in a List
Post by: BillZndl on January 28, 2015, 10:17:37 AM
Have you seen these?
http://www.theswamp.org/index.php?topic=35714.0
https://forums.autodesk.com/t5/net/example-of-a-function-in-c-that-can-be-called-from-autolisp/td-p/1631556
Title: Re: Position of Point3d in a List
Post by: It's Alive! on January 28, 2015, 03:57:36 PM
Why, if you already have a valid lisp function? If you’re looking for performance, you may not get it as passing ResultBuffers to .NET is pretty heavy

You need to parse the ResultBuffer using TypedValue’s TypeCode property, here’s a quick example

Code: [Select]
      //(doit '(((500 250 3.1) (400 600 2.2)) (((500 200 1.1) (600 700 2.3) (800 600 3.3)) ((400 100 4.1) (500 700 2.6) (200 600 3.5)))))

        [LispFunction("doit")]
        public ResultBuffer Doit(ResultBuffer inBuf)
        {
            List<Point3d> _args = null;
            List<List<Point3d>> _buf = null;
            ResultBuffer outBuf = new ResultBuffer();
            outBuf.Add(new TypedValue((short)LispDataType.ListBegin));

            if (splitDoitBuffer(inBuf, ref _args, ref _buf))
            {
                outBuf.Add(new TypedValue((short)LispDataType.Int32, _args.Count));
                outBuf.Add(new TypedValue((short)LispDataType.Int32, _buf.Count));
            }
            outBuf.Add(new TypedValue((short)LispDataType.ListEnd));
            return outBuf;
        }

        static bool splitDoitBuffer(ResultBuffer inBuf, ref List<Point3d> _args, ref List<List<Point3d>> _buf)
        {
            bool isArg = true;
            bool isInList = false;
            _buf = new List<List<Point3d>>();
            List<Point3d> subbuf = new List<Point3d>();
            foreach (TypedValue typedValue in inBuf)
            {
                switch ((LispDataType)typedValue.TypeCode)
                {
                    case LispDataType.ListBegin:
                        isInList = true;
                        break;
                    case LispDataType.ListEnd:
                        if (subbuf.Count > 0)
                        {
                            if (isArg)
                            {
                                _args = new List<Point3d>(subbuf);
                                isArg = false;
                            }
                            else
                            {
                                _buf.Add(new List<Point3d>(subbuf));
                            }
                            subbuf.Clear();
                        }
                        isInList = false;
                        break;
                    case LispDataType.Point3d:
                        if (isInList)
                            subbuf.Add((Point3d)typedValue.Value);
                        break;
                }
            }
            return (_args != null && _args.Count != 0 && _buf.Count != 0);
        }
    }
Title: Re: Position of Point3d in a List
Post by: BillZndl on January 28, 2015, 04:50:57 PM
Don't know if I did everything correctly but if you are looking for something that acts like the vl-Position function,
this a quick attempt that works inside my Autolisp program.

Code - C#: [Select]
  1. namespace FindPosition
  2. {
  3.     public class PointPositionInList
  4.     {
  5.        
  6. //AutoCad 2012 commandline//VS2010Express//NetVersion 4.
  7. //Usage - (PtPos 3dPointToFind listof3dPts) //list of 3d points in Autolisp.
  8. //thanks to CGabriel @ theswamp.org
  9.  
  10.         [LispFunction("PtPos")]        
  11.         public static int GetListInDWG(ResultBuffer args)
  12.         {            
  13.             Point3d pt = new Point3d();
  14.             List<Point3d> ptlst = new List<Point3d>();
  15.             int pos = -1;
  16.  
  17.             if (parseArguments(args))
  18.                 try
  19.                 {                    
  20.                     TypedValue[] tvArr = args.AsArray();                
  21.                  
  22.                         for (int i = 0; i < tvArr.Length; i++)
  23.                         {
  24.                             if(tvArr[i].TypeCode == RT3DPOINT)
  25.                             {                                
  26.                                 ptlst.Add((Point3d)tvArr[i].Value);
  27.                             }
  28.                         }
  29.                         pt = (Point3d)tvArr[0].Value;  //input point to find index of.
  30.                         ptlst.RemoveAt(0);             //remove input pt from start of list.                        
  31.                         pos = ptlst.IndexOf(pt);       //find index of point in remaining list.
  32.                 }
  33.                 catch (System.Exception e)
  34.                 {
  35.                     MessageBox.Show("\n Error ::: " + e.StackTrace);
  36.                 }
  37.             return pos;
  38.         }
  39.        
  40.         public static bool parseArguments(ResultBuffer args)
  41.         {
  42.             Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
  43.             if (args == null)            
  44.                 return notEnoughArguments(ed);
  45.  
  46.             ResultBufferEnumerator iter = args.GetEnumerator();
  47.  
  48.             iter.MoveNext();            
  49.             if (iter.Current.TypeCode != (int)LispDataType.Point3d) //first item in ResultBuffer is input point.              
  50.                 return wrongArguments(ed);            
  51.             if (iter.MoveNext() == false)
  52.                 return notEnoughArguments(ed);            
  53.             if (iter.Current.TypeCode != (int)LispDataType.ListBegin) //follwed by list of 3dPoints.
  54.                 return wrongArguments(ed);
  55.                 return true;
  56.         }
  57.  
  58.         public static bool notEnoughArguments(Editor ed)
  59.         {
  60.             ed.WriteMessage("\nToo few arguments.");
  61.             return false;
  62.         }
  63.  
  64.         public static bool wrongArguments(Editor ed)
  65.         {
  66.             ed.WriteMessage("\nPoint & list of 3DPoints expected.");
  67.             return false;
  68.         }
  69.  
  70.         /// <summary>
  71.         ///Thanks to Alexander Rivilis @ AutoDesk .NET forum.
  72.         /// </summary>
  73.         ///
  74.         const int RTNONE = 5000; /* No result */
  75.         const int RTREAL = 5001; /*Real number */
  76.         const int RTPOINT = 5002; /* 2D point X and Y only */
  77.         const int RTSHORT = 5003; /* Short integer */
  78.         const int RTANG = 5004; /* Angle */
  79.         const int RTSTR = 5005; /* String */
  80.         const int RTENAME = 5006; /* Entity name */
  81.         const int RTPICKS = 5007; /* Pick set */
  82.         const int RTORINT = 5008; /* Orientation */
  83.         const int RT3DPOINT = 5009; /* 3D point - X, Y, and Z */
  84.         const int RTLONG = 5010; /* Long integer */
  85.         const int RTVOID = 5014; /* Blank symbol */
  86.         const int RTLB = 5016; /* list begin */
  87.         const int RTLE = 5017; /* list end */
  88.         const int RTDOTE = 5018; /* dotted pair */
  89.         const int RTNIL = 5019; /* nil */
  90.         const int RTDXF0 = 5020; /* DXF code 0 for ads_buildlist only */
  91.         const int RTT = 5021; /* T atom */
  92.         const int RTRESBUF = 5023; /* resbuf */
  93.         const int RTMODELESS = 5027; /* interrupted by modeless dialog */
  94.          
  95.     }
  96. }
  97. [code/]
  98.  
Title: Re: Position of Point3d in a List
Post by: AARYAN on January 29, 2015, 07:46:49 AM
Why, if you already have a valid lisp function? If you’re looking for performance, you may not get it as passing ResultBuffers to .NET is pretty heavy

You need to parse the ResultBuffer using TypedValue’s TypeCode property, here’s a quick example

Thanks You so much. Yes I am looking for performance as this function could be very useful for the most of my routines which processes thousands of 3d points and with the AutoLISP code it takes a long time to process.

However I am trying to modify your code with my poor knowledge in .net (still learning) to suits my requirement but it crashes the AutoCAD. Can you please have a look and point out what is the problem and why is it happening.

Is there a way I can test code from Visual Studio because all the time I have to build a solution and netload the dll to test and if anything goes wrong I again have to start a new session of AutoCAD to test again the modified code.

AutoLISP result.
Code: [Select]
(setq a (list (list 500 400 3.3) (list 600 700 2.3) (list 800 600 2.3)))

(setq b (list (list (list 500 400 3.3) (list 800 600 2.3) (list 500 400 3.3)) (list (list 600 700 2.3) (list 500 400 3.3) (list 800 600 2.3))))

(FOREACH tr b
    (SETQ c (CONS (LIST (VL-POSITION (CAR tr) a)
(VL-POSITION (CADR tr) a)
(VL-POSITION (CADDR tr) a)) c)))

((1 0 2) (0 2 0)) => expected result

C# code
Code: [Select]
[LispFunction("GetPositions")]
        public ResultBuffer GetPositions(ResultBuffer inBuf)
        {
            List<Point3d> _args = null;
            List<List<Point3d>> _buf = null;
            List<int> _outs = null;
            ResultBuffer outBuf = new ResultBuffer();
            outBuf.Add(new TypedValue((int)LispDataType.ListBegin));

            if (splitDoitBuffer(inBuf, ref _args, ref _buf))
            {
                //outBuf.Add(new TypedValue((int)LispDataType.Int32, _args.Count));
                //outBuf.Add(new TypedValue((int)LispDataType.Int32, _buf.Count));

                foreach (List<Point3d> lpt in _buf)
                {
                    foreach (Point3d pt in lpt)
                    {
                        int i = _args.IndexOf(pt);
                        if (i != -1)
                            _outs.Add(i);
                    }
                    outBuf.Add(new TypedValue((int)LispDataType.Point3d, (new Point3d(_outs[0], _outs[1], _outs[2]))));
                }
            }
            outBuf.Add(new TypedValue((int)LispDataType.ListEnd));
            return outBuf;
        }

        static bool splitDoitBuffer(ResultBuffer inBuf, ref List<Point3d> _args, ref List<List<Point3d>> _buf)
        {
            bool isArg = true;
            bool isInList = false;
            _buf = new List<List<Point3d>>();
            List<Point3d> subbuf = new List<Point3d>();
            foreach (TypedValue typedValue in inBuf)
            {
                switch ((LispDataType)typedValue.TypeCode)
                {
                    case LispDataType.ListBegin:
                        isInList = true;
                        break;
                    case LispDataType.ListEnd:
                        if (subbuf.Count > 0)
                        {
                            if (isArg)
                            {
                                _args = new List<Point3d>(subbuf);
                                isArg = false;
                            }
                            else
                            {
                                _buf.Add(new List<Point3d>(subbuf));
                            }
                            subbuf.Clear();
                        }
                        isInList = false;
                        break;
                    case LispDataType.Point3d:
                        if (isInList)
                            subbuf.Add((Point3d)typedValue.Value);
                        break;
                }
            }
            return (_args != null && _args.Count != 0 && _buf.Count != 0);
        }

Hope my expectations are not too much.

Thanks for any help.

Best Regards