ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C#/AutoCAD] Rectangle Jig
    C#/AutoCAD API 2023. 9. 8. 06:09

    command 'rect'와 동일한 효과를 .net API로 구현하려면 아래의 코드대로 구현한다.

    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.EditorInput;
    using Autodesk.AutoCAD.Geometry;
    using Autodesk.AutoCAD.Runtime;
    using static System.Math;
    using AcAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;
    using AcGi = Autodesk.AutoCAD.GraphicsInterface;
    
    [assembly: CommandClass(typeof(RectangleJigSample.Commands))]
    
    namespace RectangleJigSample
    {
        public class Commands
        {
            [CommandMethod("TEST")]
            public void Test()
            {
                var doc = AcAp.DocumentManager.MdiActiveDocument;
                var db = doc.Database;
                var ed = doc.Editor;
                var ppr = ed.GetPoint("\nSpecify first corner point: ");
                if (ppr.Status != PromptStatus.OK)
                    return;
                var pt = ppr.Value;
                using (var tr = db.TransactionManager.StartTransaction())
                using (var pline = new Polyline(4))
                {
                    pline.AddVertexAt(0, new Point2d(pt.X, pt.Y), 0.0, 0.0, 0.0);
                    pline.AddVertexAt(1, new Point2d(pt.X + 1.0, pt.Y), 0.0, 0.0, 0.0);
                    pline.AddVertexAt(2, new Point2d(pt.X + 1.0, pt.Y + 1.0), 0.0, 0.0, 0.0);
                    pline.AddVertexAt(3, new Point2d(pt.X, pt.Y + 1.0), 0.0, 0.0, 0.0);
                    pline.Closed = true;
                    pline.Elevation = pt.Z;
                    var ucs = ed.CurrentUserCoordinateSystem;
                    pline.TransformBy(ucs);
    
                    // create a RectangleJig
                    var rectJig = new RectangleJig(pline, 0.0);
    
                    // Loop while the user specify other corner or cancel
                    while (true)
                    {
                        var pr = ed.Drag(rectJig);
                        // Other corner is specified
                        if (pr.Status == PromptStatus.OK)
                        {
                            var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                            curSpace.AppendEntity(pline);
                            tr.AddNewlyCreatedDBObject(pline, true);
                            break;
                        }
                        // Rotation option
                        if (pr.Status == PromptStatus.Keyword)
                        {
                            // use a RotationJig to get the rectangle rotation
                            var rotJig = new RotationJig(pline, pline.GetPoint3dAt(0), pline.Normal);
                            var result = ed.Drag(rotJig);
                            if (result.Status == PromptStatus.OK)
                                rectJig = new RectangleJig(pline, rotJig.Rotation);
                            else
                                break;
                        }
                        // Cancel
                        else
                            break;
                    }
                    tr.Commit();
                }
            }
        }
    
        public struct Rectangle
        {
            public Point2d Point0 { get; }
            public Point2d Point1 { get; }
            public Point2d Point2 { get; }
            public Point2d Point3 { get; }
    
            public Rectangle(Point2d firstCorner, Point2d oppositeCorner, double rotation)
            {
                Vector2d u = new Vector2d(Cos(rotation), Sin(rotation));
                Vector2d v = new Vector2d(-Sin(rotation), Cos(rotation));
                Vector2d diag = firstCorner.GetVectorTo(oppositeCorner);
                Point0 = firstCorner;
                Point1 = firstCorner + u * u.DotProduct(diag);
                Point2 = oppositeCorner;
                Point3 = firstCorner + v * v.DotProduct(diag);
            }
        }
    
        public class RectangleJig : EntityJig
        {
            Polyline pline;
            double ucsRot, rotation;
            Plane plane;
            Point3d dragPt, basePt;
            Point2d pt2D;
            Editor ed;
            CoordinateSystem3d ucs;
    
            public RectangleJig(Polyline pline, double rotation) : base(pline)
            {
                this.pline = pline;
                this.rotation = rotation;
                plane = new Plane(Point3d.Origin, pline.Normal);
                basePt = pline.GetPoint3dAt(0);
                pt2D = pline.GetPoint2dAt(0);
                ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
                ucs = ed.CurrentUserCoordinateSystem.CoordinateSystem3d;
                Matrix3d mat = Matrix3d.WorldToPlane(plane);
                ucsRot = Vector3d.XAxis.GetAngleTo(ucs.Xaxis.TransformBy(mat), Vector3d.ZAxis);
            }
    
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                var msg = "\nSpecify other corner point or [Rotation]: ";
                var options = new JigPromptPointOptions(msg, "Rotation");
                options.AppendKeywordsToMessage = true;
                options.UseBasePoint = true;
                options.BasePoint = basePt;
                options.UserInputControls =
                    UserInputControls.Accept3dCoordinates |
                    UserInputControls.UseBasePointElevation;
                PromptPointResult result = prompts.AcquirePoint(options);
                if (result.Status == PromptStatus.Keyword)
                {
                    pline.TransformBy(Matrix3d.Rotation(-rotation, pline.Normal, basePt));
                    return SamplerStatus.OK;
                }
                if (result.Value.IsEqualTo(dragPt))
                    return SamplerStatus.NoChange;
    
                dragPt = result.Value;
                return SamplerStatus.OK;
            }
    
            protected override bool Update()
            {
                var rectangle = new Rectangle(pt2D, dragPt.Convert2d(plane), rotation + ucsRot);
                pline.SetPointAt(1, rectangle.Point1);
                pline.SetPointAt(2, rectangle.Point2);
                pline.SetPointAt(3, rectangle.Point3);
                return true;
            }
        }
    
        public class RotationJig : DrawJig
        {
            Entity entity;
            double rotation;
            Point3d basePoint;
            Vector3d normal;
    
            public double Rotation => rotation;
    
            public RotationJig(Entity entity, Point3d basePoint, Vector3d normal)
            {
                this.entity = entity;
                this.basePoint = basePoint;
                this.normal = normal;
            }
    
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                var options = new JigPromptAngleOptions("\nSpecify rotation angle: ");
                options.BasePoint = basePoint;
                options.UseBasePoint = true;
                options.Cursor = CursorType.RubberBand;
                options.UserInputControls =
                    UserInputControls.Accept3dCoordinates |
                    UserInputControls.UseBasePointElevation;
                var result = prompts.AcquireAngle(options);
                if (result.Value == rotation)
                    return SamplerStatus.NoChange;
                rotation = result.Value;
                return SamplerStatus.OK;
            }
    
            protected override bool WorldDraw(AcGi.WorldDraw draw)
            {
                AcGi.WorldGeometry geom = draw.Geometry;
                if (geom != null)
                {
                    geom.PushModelTransform(Matrix3d.Rotation(rotation, normal, basePoint));
                    geom.Draw(entity);
                    geom.PopModelTransform();
                }
                return true;
            }
        }
    }

    출처 : https://forums.autodesk.com/t5/net/rectanglejig-question/td-p/7412563

Designed by Tistory.