Jump to content

Recommended Posts

Posted

Hi.
I can't pass the second argument, a list of 3D points.
Point format:

(list (list x1 y1 z1) (list x2 y2 z2)...)

Where am I missing something?
The code itself:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;

public class LispFunctions
{
    [LispFunction("CountPointsInsidePolyline")]
    public static int CountPointsInsidePolyline(ResultBuffer resBuf)
    {
        // Get the current document and editor
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Editor ed = doc.Editor;
        Database db = doc.Database;

        try
        {
            // Check input arguments
            if (resBuf == null)
            {
                throw new ArgumentNullException(nameof(resBuf), "No arguments provided");
            }

            TypedValue[] argsArray = resBuf.AsArray();

            // Check the number of arguments (should be exactly 2)
            if (argsArray.Length != 2)
            {
                throw new ArgumentException("Exactly 2 arguments required: polyline and point list");
            }

            // Get the polyline
            if (!(argsArray[0].Value is ObjectId polylineId))
            {
                throw new ArgumentException("First argument must be a polyline");
            }

            // Get the point list
            List<Point3d> points = new List<Point3d>();
            if (argsArray[1].Value is ResultBuffer pointsBuffer)
            {
                foreach (TypedValue value in pointsBuffer)
                {
                    if (value.TypeCode == (int)LispDataType.ListBegin)
                    {
                        ResultBuffer coordBuffer = value.Value as ResultBuffer;
                        if (coordBuffer != null && coordBuffer.AsArray().Length >= 3)
                        {
                            double[] coords = coordBuffer.AsArray()
                                .Take(3)
                                .Select(c => Convert.ToDouble(c.Value))
                                .ToArray();
                            points.Add(new Point3d(coords[0], coords[1], coords[2]));
                        }
                    }
                    else if (value.TypeCode == (int)LispDataType.Point3d)
                    {
                        points.Add((Point3d)value.Value);
                    }
                }
            }
            else
            {
                throw new ArgumentException("Second argument must be a point list");
            }

            int count = 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    // Get the polyline
                    Entity entity = tr.GetObject(polylineId, OpenMode.ForRead) as Entity;
                    if (entity == null || !IsClosedPolyline(entity))
                    {
                        throw new ArgumentException("Object is not a closed polyline");
                    }

                    if (!(entity is Curve curve))
                    {
                        throw new ArgumentException("Object is not a curve");
                    }

                    // Get 2D polygon for checking
                    List<Point2d> polygon = GetPolygonPoints(curve, tr);

                    // Check each point
                    foreach (Point3d pt in points)
                    {
                        Point2d checkPoint = new Point2d(pt.X, pt.Y);
                        if (IsPointInPolygon(polygon, checkPoint))
                            count++;
                    }

                    tr.Commit();
                    return count;
                }
                catch
                {
                    tr.Abort();
                    throw;
                }
            }
        }
        catch (System.Exception ex)
        {
            ed.WriteMessage($"\nError: {ex.Message}");
            return 0;
        }
    }

    private static bool IsClosedPolyline(Entity entity)
    {
        switch (entity)
        {
            case Polyline pl:
                return pl.Closed;
            case Polyline2d pl2d:
                return pl2d.Closed;
            default:
                return false;
        }
    }

    private static List<Point2d> GetPolygonPoints(Curve curve, Transaction tr)
    {
        List<Point2d> points = new List<Point2d>();

        if (curve is Polyline pl)
        {
            for (int i = 0; i < pl.NumberOfVertices; i++)
            {
                Point3d pt3d = pl.GetPoint3dAt(i);
                points.Add(new Point2d(pt3d.X, pt3d.Y));
            }
        }
        else if (curve is Polyline2d pl2d)
        {
            foreach (ObjectId vxId in pl2d)
            {
                Vertex2d vx = tr.GetObject(vxId, OpenMode.ForRead) as Vertex2d;
                if (vx != null)
                {
                    Point3d pt3d = vx.Position;
                    points.Add(new Point2d(pt3d.X, pt3d.Y));
                }
            }
        }

        return points;
    }

    private static bool IsPointInPolygon(List<Point2d> polygon, Point2d point)
    {
        bool inside = false;
        int count = polygon.Count;

        for (int i = 0, j = count - 1; i < count; j = i++)
        {
            if (((polygon[i].Y > point.Y) != (polygon[j].Y > point.Y)) &&
                (point.X < (polygon[j].X - polygon[i].X) * (point.Y - polygon[i].Y) /
                (polygon[j].Y - polygon[i].Y) + polygon[i].X))
            {
                inside = !inside;
            }
        }

        return inside;
    }
}

 

Posted

The system is going to convert those lists into points for you,

in your typed value, just check that the type is Point3d

 

from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax
import traceback

@Ap.LispFunction()
def countPointsInsidePolyline(buffer):
    try:
        points = []
        for type, value in buffer:
            if type == Rx.LispType.kPoint3d:
                points.append(value)
        return len(points)
    except Exception as err:
        traceback.print_exception(err)

 

(countPointsInsidePolyline '(1.0 2.0 3.0) '(1.0 2.0 3.0))

 

returns 2

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...