Author Topic: More C# Extension Methods  (Read 11073 times)

0 Members and 2 Guests are viewing this topic.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8843
  • AKA Daniel
More C# Extension Methods
« on: November 22, 2007, 01:51:00 PM »
Maybe some of these ResultBuffer methods might be useful…if they work  :laugh:

Code: [Select]
namespace LispBase
{
  public static class ResultBufferExtension
  {
    //add
    public static void Add(this ResultBuffer m_this, int typecode)
    {
      m_this.Add(new TypedValue(typecode));
    }
    public static void Add(this ResultBuffer m_this, int typecode, object value)
    {
      m_this.Add(new TypedValue(typecode, value));
    }
    public static void Add(this ResultBuffer m_this, LispDataType type)
    {
      m_this.Add(new TypedValue((int)type));
    }
    public static void Add(this ResultBuffer m_this, LispDataType type, object value)
    {
      m_this.Add(new TypedValue((int)type, value));
    }
    public static void Add(this ResultBuffer m_this, DxfCode type)
    {
      m_this.Add(new TypedValue((int)type));
    }
    public static void Add(this ResultBuffer m_this, DxfCode type, object value)
    {
      m_this.Add(new TypedValue((int)type, value));
    }

    //AddRange
    public static void AddRange(this ResultBuffer m_this, ResultBuffer src)
    {
      if (src == null)
        throw new ArgumentNullException();

      foreach (TypedValue e in src)
        m_this.Add(e);

    }
    public static void AddRange(this ResultBuffer m_this, TypedValue[] src)
    {
      if (src == null)
        throw new ArgumentNullException();

      foreach (TypedValue e in src)
        m_this.Add(e);

    }
    public static void AddRange(this ResultBuffer m_this, IEnumerable<TypedValue> src)
    {
      if (src == null)
        throw new ArgumentNullException();

      foreach (TypedValue e in src)
        m_this.Add(e);

    }

    //Some Lisp stuff .. add what you need
    public static void AddLispT(this ResultBuffer m_this)
    {
      m_this.Add(new TypedValue((int)LispDataType.T_atom));
    }
    public static void AddLispNil(this ResultBuffer m_this)
    {
      m_this.Add(new TypedValue((int)LispDataType.Nil));
    }
    public static void AddLispString(this ResultBuffer m_this, string str)
    {
      m_this.Add(new TypedValue((int)LispDataType.Text, str));
    }
    public static void AddLispDouble(this ResultBuffer m_this, double num)
    {
      m_this.Add(new TypedValue((int)LispDataType.Double, num));
    }
    public static void AddLispInt(this ResultBuffer m_this, int num)
    {
      m_this.Add(new TypedValue((int)LispDataType.Int32, num));
    }
    public static void AddLispErr(this ResultBuffer m_this, string message)
    {
      m_this.Add(new TypedValue((int)LispDataType.Nil));
      m_this.Add(new TypedValue((int)LispDataType.DottedPair));
      m_this.Add(new TypedValue((int)LispDataType.Text, "Error: " + message));
    }

    //
    public static void ForEach(this ResultBuffer m_this, Action<TypedValue> action)
    {
      if (action == null)
        throw new ArgumentNullException();

      foreach (TypedValue e in m_this)
        action(e);
    }

    //
    public static TypedValue GetAt(this ResultBuffer m_this, int index)
    {
      return m_this.AsArray()[index];
    }

    //
    public static int GetCount(this ResultBuffer m_this)
    {
      int cnt = 0;

      foreach (TypedValue e in m_this)
        cnt += 1;

      return cnt;
    }

    //
    public static List<TypedValue> ToList(this ResultBuffer m_this)
    {
      return new List<TypedValue>(m_this.AsArray());
    }

    //add some LinQ
    public static IEnumerable<TypedValue> Where
      (this ResultBuffer m_this, Func<TypedValue, bool> predicate)
    {
      foreach (TypedValue element in m_this)
      {
        if (predicate(element) == true)
          yield return element;
      }
    }

    public static IEnumerable<TypedValue> Select
      (this ResultBuffer m_this, Func<TypedValue, TypedValue> selector)
    {
      foreach (TypedValue element in m_this)
      {
        yield return selector(element);
      }
    }
  }
}

Edit:  added lisp stuff
« Last Edit: November 24, 2007, 12:47:01 AM by Daniel »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8843
  • AKA Daniel
Re: More C# Extension Methods
« Reply #1 on: November 22, 2007, 09:52:47 PM »
example

Code: [Select]
[LispFunction("test")]
    static public ResultBuffer test(ResultBuffer Args)
    {
      ResultBuffer RetRb = new ResultBuffer();

      try
      {
        Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

        if (Args == null)
        {
          RetRb.AddLispErr("Null Argument");
          return RetRb;
        }
        if (Args.GetCount() == 0)
        {
          RetRb.AddLispErr("To Few Arguments");
          return RetRb;
        }

        Args.ForEach(p => ed.WriteMessage("\n" + p.Value.ToString()));

        RetRb.AddLispT();

      }
      catch (System.Exception ex)
      {
        RetRb.AddLispErr(ex.Message);
      }
      return RetRb;
    }

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: More C# Extension Methods
« Reply #2 on: November 23, 2007, 04:43:34 PM »

good food for thought Daniel ..
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: 8843
  • AKA Daniel
Re: More C# Extension Methods
« Reply #3 on: November 24, 2007, 12:54:17 AM »

good food for thought Daniel ..

Thanks Kerry

I added a couple of LinQ methods (original source) so we can query a Resultbuffer  :laugh:

Sample:

Code: [Select]
amespace LispBase
{
  public class Commands
  {
    //(test1 1 1 "Hello")
    [LispFunction("test1")]
    public static ResultBuffer test1(ResultBuffer args)
    {
      ResultBuffer retList = new ResultBuffer();
      try
      {
        Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

        if (args == null)
        {
          retList.AddLispErr("Null Argument");
          return retList;
        }
        if (args.GetCount() == 0)
        {
          retList.AddLispErr("To Few Arguments");
          return retList;
        }

        Func<TypedValue, bool>
          filter = x => x.TypeCode == (int)LispDataType.Text;

        var rlist = args.Where(filter);

        foreach (var e in rlist)
          retList.AddLispString(e.Value.ToString());

    
        if (retList.GetCount() == 0)
        {
          retList.AddLispNil();
          return retList;
        }

      }
      catch (System.Exception ex)
      {
        retList.AddLispErr(ex.Message);
      }
      return retList;
    }


    //(test2 "s" "a" "s" "a" "ad")
    [LispFunction("test2")]
    public static ResultBuffer test2(ResultBuffer args)
    {
      ResultBuffer retList = new ResultBuffer();
      try
      {

        Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

        if (args == null)
        {
          retList.AddLispErr("Null Argument");
          return retList;
        }
        if (args.GetCount() == 0)
        {
          retList.AddLispErr("To Few Arguments");
          return retList;
        }

        var query = from f in args
                    where f == new TypedValue((int)LispDataType.Text, "a")
                    select f;

        foreach (var e in query)
          retList.AddLispString((string)e.Value);

        if (retList.GetCount() == 0)
        {
          retList.AddLispNil();
          return retList;
        }

      }
      catch (System.Exception ex)
      {
        retList.AddLispErr(ex.Message);
      }
      return retList;
    }
  }
}

added: All while eating Aussie Black Opal licorice  :|
« Last Edit: November 24, 2007, 01:09:52 AM by Daniel »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: More C# Extension Methods
« Reply #4 on: November 24, 2007, 02:07:37 AM »
..............
added: All while eating Aussie Black Opal licorice  :|

hmmmmm , yum  !

though I have a preference for Darell Lea Liquorice myself

.. I have a pack on my desk as we speak :-)

exemplifies 'coding for food' hey ?
« Last Edit: November 24, 2007, 02:10:20 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.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8843
  • AKA Daniel
Re: More C# Extension Methods
« Reply #5 on: November 24, 2007, 08:00:13 PM »
Here is another sample, gets the object id’s of the Entities in a selection set with
XData containing a specific value, using our new LinQ enabled Resultbuffer

Code: [Select]
    [CommandMethod("test")]
    static public void test()
    {
      Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

      TypedValue[] values = new TypedValue[]
                     {
                        new TypedValue((short)DxfCode.Start, "LINE") ,
                        new TypedValue((short)DxfCode.XDataStart) ,
                        new TypedValue((short)DxfCode.ExtendedDataRegAppName, "Dan")
                     };

      SelectionFilter filter = new SelectionFilter(values);
      PromptSelectionOptions selopts = new PromptSelectionOptions();
      selopts.MessageForAdding = "Select";
      selopts.AllowDuplicates = false;
      PromptSelectionResult result = ed.GetSelection(selopts, filter);

      if (result.Status == PromptStatus.OK)
      {
        ObjectId[] idarray = result.Value.GetObjectIds();

        List<ObjectId> rlist = new List<ObjectId>();

        Autodesk.AutoCAD.DatabaseServices.TransactionManager tm =
           Application.DocumentManager.MdiActiveDocument.Database.TransactionManager;

        //our filter
        TypedValue Xdatafilter = new TypedValue((int)DxfCode.ExtendedDataAsciiString, "a");

        Transaction tr = tm.StartTransaction();
        try
        {
          foreach (ObjectId id1 in idarray)
          {

            Entity ent = (Entity)tm.GetObject(id1, OpenMode.ForRead, true);
            ResultBuffer xRb = ent.XData;

            //using our Extension method here
            var query = xRb.Where(p => p.Equals(Xdatafilter));

            //or

            // a LinQ Style query
            //var query = from f in xRb
            //            where f == Xdatafilter
            //            select f;

            if (query.Count() != 0)
            {
              rlist.Add(ent.ObjectId);
            }
          }

          //using our Extension method here
          rlist.ForEach(p => ed.WriteMessage("\n" + p.ToString()));
        }
        catch (System.Exception ex)
        {
          ed.WriteMessage(ex.Message);
        }
        finally
        {
          tr.Dispose();
        }
      }
    }

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: More C# Extension Methods
« Reply #6 on: November 27, 2007, 07:48:27 PM »
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: 8843
  • AKA Daniel
Re: More C# Extension Methods
« Reply #7 on: December 03, 2007, 02:36:56 AM »
Just a quick bunch of extension methods attached (still under construction)
.NET 3.5

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: More C# Extension Methods
« Reply #8 on: December 03, 2007, 02:45:56 AM »

The BulgeVertex extension looks handy Daniel.

Thanks, I'll have a peek when things settle down. Looks like fun.
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: 8843
  • AKA Daniel
Re: More C# Extension Methods
« Reply #9 on: December 03, 2007, 03:43:08 AM »
My first goal is just to run through most of the collections and add AddRange(), ForEach(),  Where() and Select()  extension methods,
IMO very handy stuff.

SomeCallMeDave

  • Guest
Re: More C# Extension Methods
« Reply #10 on: December 08, 2007, 06:28:32 PM »
Daniel,
Very cool stuff, even for a C# beginner like me.

Here are my first feeble attempts to extend the polyline class

Code: [Select]
    public static class EntityExtentions
    {
        internal static Double GetRadiusFromParam(this Polyline pline, double pParam)
        {
            if (pline == null)
            {
                throw new ArgumentNullException();
            }//if
            double cbulge = 0.0;
            if (pParam < pline.EndParam)
            {
                cbulge = pline.GetBulgeAt((int)pParam);
            }
            else
            {
                return 0.0;
            }
           
            if (cbulge == 0.0)
            {
                return 0.0;
            }
            // bulge is not Zero and the vertexindex is not at the end so continue...
            Point2d p1 = pline.GetPoint2dAt((int)pParam);
            Point2d p2 = pline.GetPoint2dAt((int)pParam + 1);
            double delta = 4 * Math.Atan(Math.Abs(cbulge));
            double chord = Math.Sqrt(Math.Pow((p1.X-p2.X),2) + Math.Pow((p1.Y-p2.Y),2));
            double radius = Math.Abs(chord / (2 * Math.Sin(delta / 2)));

            return radius;
        }//GetRadiusFromParam

        internal static Point3d GetRadiusPointFromParam(this Polyline pline, double pParam)
        {
            if (pline == null)
            {
                throw new ArgumentNullException();
            }//if
            double cbulge = 0.0;
            if (pParam < pline.EndParam)
            {
                cbulge = pline.GetBulgeAt((int)pParam);
            }
            else
            {
                //not the best choice of return value
                return new Point3d(0, 0, 0);
            }

            if (cbulge == 0.0)
            {
                //not the best choice of return value
                return new Point3d(0, 0, 0);
            }

            // bulge is not Zero and the vertexindex is not at the end so continue...
            Point2d p1 = pline.GetPoint2dAt((int)pParam);
            Point2d p2 = pline.GetPoint2dAt((int)pParam + 1);
            double delta = 4 * Math.Atan(Math.Abs(cbulge));
            double chord = p1.GetDistanceTo(p2);
            double radius = Math.Abs(chord / (2 * Math.Sin(delta / 2)));
            Point3d midp = pline.GetPointAtParameter((int)pParam + 0.5);
            Line l1 = new Line(new Point3d(p1.X, p1.Y, 0), new Point3d(p2.X, p2.Y, 0));
            Point3d midc = l1.GetPointAtParameter(chord/2.0);
            Line l2 = new Line(midp, midc);
            double sf = radius/l2.GetDistanceAtParameter(l2.EndParam);
            Vector3d v1 = midp.GetAsVector();
            Vector3d v2 = midc.GetAsVector();

            Vector3d v3 = v2- v1;
            Vector3d v4 = v3 * sf;


            Vector3d vRadPt = v4.Add(v1);

            Point3d radPt = new Point3d(vRadPt.ToArray());

            return radPt;
        }//GetRadiusPointFromParam
  }


I have a lot to learn, but it's going to be fun. 

Thanks in advance for fielding all my up-coming questions  :)

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8843
  • AKA Daniel
Re: More C# Extension Methods
« Reply #11 on: December 09, 2007, 06:15:57 AM »
Wow! Welcome to the party David!  :laugh:
Nice Coding!

sinc

  • Guest
Re: More C# Extension Methods
« Reply #12 on: December 09, 2007, 10:20:39 AM »
Hey, Dave, check this out.  It is similar to the routine you wrote.  This routine returns a negative radius if the radius is on the "left" side of the polyline.

Code: [Select]
    public struct RadiusPoint
    {
        public double Radius;
        public Point3d Point;
    }

    public class CurveUtil
    {
        public static RadiusPoint SegmentRadiusPoint(Polyline pline, double param)
        {
            RadiusPoint rp = new RadiusPoint();
            double buldge = pline.GetBulgeAt(Convert.ToInt32(param));
            if (Math.Abs(buldge) > 0)
            {
                Vector3d vec = pline.GetSecondDerivative(param);
                int buldgeDir = (buldge > 0) ? -1 : 1;
                rp.Radius = vec.Length * buldgeDir;
                rp.Point = pline.GetPointAtParameter(param).Subtract(vec * buldgeDir);
            }
            return rp;
        }
    }

SomeCallMeDave

  • Guest
Re: More C# Extension Methods
« Reply #13 on: December 10, 2007, 07:41:57 AM »
Wow! Welcome to the party David!  :laugh:
Nice Coding!

Thanks Daniel.  I'm having fun!!!.  But the coding is mostly yours with some of my LISP functions translated to C#  :)

Sinc,  nice function!!!  Much more succinct than mine.   One question -   is Convert.ToInt32(param) preferred over a cast (int)param ?  Are there benefits and/or costs associated with either?

sinc

  • Guest
Re: More C# Extension Methods
« Reply #14 on: December 10, 2007, 08:15:13 AM »
Oh, I doubt it.

I'm still pretty new to C# and .NET, and sometimes I do silly things.   :-D