• Industries
  • Products
  • Buy
  • Services & Support
  • Communities
  • Discussion Groups

    .NET

    Reply
    Distinguished Contributor
    vince1327
    Posts: 117
    Registered: ‎11-02-2011
    Accepted Solution

    Area, Length and Width of last object created

    362 Views, 7 Replies
    04-13-2012 06:34 AM

    Hey guys,

     

    I'm trying to prompt a user to create a rectangle to use as a selection box to later layout blocks. The native rectangle command in AutoCAD 2012 is perfect but i need to get the area, length and width of the rectangle...is there a way that i could use something like editor.selectlast to figure this out?

     

    Cheers

    Vince

    Please use plain text.
    *Expert Elite*
    Hallex
    Posts: 1,332
    Registered: ‎10-08-2008

    Re: Area, Length and Width of last object created

    04-13-2012 07:14 AM in reply to: vince1327

    Not sure about A2012 but maybe this helps

     <CommandMethod("Selast")> _
        Public Sub testbox()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument()
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Dim res As PromptSelectionResult
            res = ed.SelectLast
            Try
                Using tr As Transaction = db.TransactionManager.StartTransaction
                    Dim ent As Entity = tr.GetObject(res.Value.GetObjectIds(0), OpenMode.ForRead)
                    Dim ecs As Extents3d = ent.GeometricExtents
                    Dim leng As Double = ecs.MaxPoint.X - ecs.MinPoint.X
                    Dim wid As Double = ecs.MaxPoint.Y - ecs.MinPoint.Y
                    Dim ar As Double = leng * wid
                    ed.WriteMessage(vbCr + "Length: {0}; Width: {1}; Area: {2}", leng, wid, ar)
                End Using
            Catch exs As System.Exception
                ed.WriteMessage(exs.Message & vbLf & exs.StackTrace)
            Finally
    
            End Try
        End Sub

     

    ~'J'~

    _____________________________________
    C6309D9E0751D165D0934D0621DFF27919
    Please use plain text.
    Distinguished Contributor
    vince1327
    Posts: 117
    Registered: ‎11-02-2011

    Re: Area, Length and Width of last object created

    04-13-2012 07:36 AM in reply to: Hallex

    Thanks Hallex, i'm going to try this out now and i'll report back. Would it be easier to just use the "area" command in autoCAD as my selection box as it provides all the info right away as well as a nice interface? If so, is it still possible to return the values for area, length and width into my code?

     

    Cheers

    Vince

    Please use plain text.
    Distinguished Contributor
    vince1327
    Posts: 117
    Registered: ‎11-02-2011

    Re: Area, Length and Width of last object created

    04-13-2012 07:56 AM in reply to: Hallex

    I've just worked this back into C# but am running into an error on this line:

     

    Entity ent = tr.GetObject(resr.Value.GetObjectIds(0), OpenMode.ForRead) as Entity;

     

    The error I get is that  "No overload for method 'GetObjectIDs' takes 1 arguments" and "Argument 1: cannot convert from 'Autodesk.AutoCAD.DatabaseServices.ObjectId[] to 'Autodesk.AutoCAD.DatabaseServices.ObjectId'

     

    Is this something ridiculously simple??

     

    Cheers

    Vince

     

    // Option 1 ... User Selects Rectangle as Shape
                if (sres.StringResult == "rect")
                {
                    Document docr = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
                    Database dbr = doc.Database;
                    Editor edr = doc.Editor;
                    Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
                    PromptSelectionResult resr = new PromptSelectionResult();
                    resr = ed.SelectLast();
                    acDoc.SendStringToExecute("._rectangle ", true, false, false);
    
                   
    
                       Transaction tr = db.TransactionManager.StartTransaction();
                       using (tr)
                       {
                           //Entity ent = tr.GetObject(resr.Value.GetObjectIds(0), OpenMode.ForRead) as Entity;
                           Entity ent = tr.GetObject(resr.Value.GetObjectIds(0), OpenMode.ForRead) as Entity;
                           Extents3d ecs = ent.GeometricExtents;
                           double leng = ecs.MaxPoint.X - ecs.MinPoint.X;
                           double wid = ecs.MaxPoint.Y - ecs.MinPoint.Y;
                           double ar = leng * wid;
                           edr.WriteMessage("Length = " + leng);
    
                           edr.WriteMessage("Width = " + wid);
    
                           edr.WriteMessage("Area = " + ar);
                       }

     

    Please use plain text.
    *Expert Elite*
    Hallex
    Posts: 1,332
    Registered: ‎10-08-2008

    Re: Area, Length and Width of last object created

    04-13-2012 08:41 AM in reply to: vince1327

    You can stay avoid SendStringToExecute I think

    Perhaps it will help as well:

        <CommandMethod("Selast")> _
        Public Sub testbox()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument()
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Dim res As PromptSelectionResult
            res = ed.SelectLast
            Try
                Using tr As Transaction = db.TransactionManager.StartTransaction
                    Dim ent As Entity = tr.GetObject(res.Value.GetObjectIds(0), OpenMode.ForRead)
                    Dim ecs As Extents3d = ent.GeometricExtents
                    Dim leng As Double = ecs.MaxPoint.X - ecs.MinPoint.X
                    Dim wid As Double = ecs.MaxPoint.Y - ecs.MinPoint.Y
                    Dim ar As Double = leng * wid
                    ed.WriteMessage(vbCr + "Length: {0}; Width: {1}; Area: {2}", leng, wid, ar)
                    Dim pres As PromptSelectionResult
                    'pres = ed.SelectCrossingWindow(ecs.MinPoint, ecs.MaxPoint) ''<-- you can add the filter there, e.g.:
                    ''----------------------------------------------------------------------------------------------------''
                    Dim filterList(,) As Object = New Object(,) {{-4, "<or"}, {0, "Line"}, {0, "Polyline"}, {0, "Insert"}, {0, "Circle"}, {0, "Circle"}, {-4, "or>"}} '' и т. д.
                    Dim tvs(filterList.GetUpperBound(0)) As TypedValue
                    For i As Integer = 0 To filterList.GetUpperBound(0)
                        tvs(i) = New TypedValue(Convert.ToInt32(filterList(i, 0)), filterList(i, 1))
                    Next
                    Dim filt As SelectionFilter = New SelectionFilter(tvs)
                    pres = ed.SelectCrossingWindow(ecs.MinPoint, ecs.MaxPoint, filt) ''<-- the filter added
                    ''----------------------------------------------------------------------------------------------------''
                    If pres IsNot Nothing Then
                        For Each selobj As SelectedObject In pres.Value
                            Dim obj As Entity = tr.GetObject(selobj.ObjectId, OpenMode.ForRead)
                            ed.WriteMessage(vbLf + obj.GetRXClass().DxfName)
                        Next
                    End If
                End Using
            Catch exs As System.Exception
                ed.WriteMessage(exs.Message & vbLf & exs.StackTrace)
            Finally
    
            End Try
        End Sub

     

     

    ~'J'~

     

    _____________________________________
    C6309D9E0751D165D0934D0621DFF27919
    Please use plain text.
    *Expert Elite*
    Posts: 1,639
    Registered: ‎04-29-2006

    Re: Area, Length and Width of last object created

    04-13-2012 02:12 PM in reply to: vince1327

    Hi,

     

    You may avoid using SendStringToexecute because it doesn't run synchronously.

     

    You can define a 'Rectangle' Type with the properties and method you need.

    Here's an example:

     

            public class Rectangle
            {
                // constructor
                public Rectangle(Point3d p1, Point3d p2)
                {
                    LowerLeft = new Point3d(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y), 0.0);
                    UpperRight = new Point3d(Math.Max(p1.X, p2.X), Math.Max(p1.Y, p2.Y), 0.0);
                    Length = UpperRight.X - LowerLeft.X;
                    Width = UpperRight.Y - LowerLeft.Y;
                    Area = Length * Width;
                }
     
                // public read only properties
                public Point3d LowerLeft { getprivate set; }
                public Point3d UpperRight { getprivate set; }
                public double Length { getprivate set; }
                public double Width { getprivate set; }
                public double Area { getprivate set; }
                public SelectionSet CrossingSelectionSet
                {
                    get { return Select(true); }
                }
                public SelectionSet WindowSelectionSet
                {
                    get { return Select(false); }
                }
     
                // public method, draws the rectangle in the current space.
                public void Draw()
                {
                    Database db = HostApplicationServices.WorkingDatabase;
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                        using (Polyline pline = new Polyline())
                        {
                            pline.AddVertexAt(0, new Point2d(LowerLeft.X, LowerLeft.Y), 0.0, 0.0, 0.0);
                            pline.AddVertexAt(1, new Point2d(UpperRight.X, LowerLeft.Y), 0.0, 0.0, 0.0);
                            pline.AddVertexAt(2, new Point2d(UpperRight.X, UpperRight.Y), 0.0, 0.0, 0.0);
                            pline.AddVertexAt(3, new Point2d(LowerLeft.X, UpperRight.Y), 0.0, 0.0, 0.0);
                            pline.Closed = true;
                            btr.AppendEntity(pline);
                            tr.AddNewlyCreatedDBObject(pline, true);
                        }
                        tr.Commit();
                    }
                }
     
                // public static method, creates a new instance of Rectangle if the user specifies two points
                public static Rectangle Create()
                {
                    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                    PromptPointResult ppr = ed.GetPoint("\nFirst corner: ");
                    if (ppr.Status == PromptStatus.Cancel)
                        return null;
                    Point3d pt = ppr.Value;
                    ppr = ed.GetCorner("\nSecond corner: ", pt);
                    if (ppr.Status == PromptStatus.Cancel)
                        return null;
                    Matrix3d ucs = ed.CurrentUserCoordinateSystem;
                    return new Rectangle(pt.TransformBy(ucs), ppr.Value.TransformBy(ucs));
                }
     
                // private method, returns the selection set
                private SelectionSet Select(bool crossing)
                {
                    Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
                    Matrix3d wcs = ed.CurrentUserCoordinateSystem.Inverse();
                    return crossing ?
                        ed.SelectCrossingWindow(LowerLeft.TransformBy(wcs), UpperRight.TransformBy(wcs)).Value :
                        ed.SelectWindow(LowerLeft.TransformBy(wcs), UpperRight.TransformBy(wcs)).Value;
                }
            }

     

    Then, using this type, you can prompt the user to draw a rectangle the same wat as the native AutoCAD Command, get the data you need (length, width and area), use the rectangle to get a selection set.

     

    Here's a little example:

     

           
            [CommandMethod("test")]
            public void test()
            {
                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                Rectangle rect = Rectangle.Create();
                if (rect == null) 
                    return;
                SelectionSet ss = rect.WindowSelectionSet;
                ed.SetImpliedSelection(ss);
                rect.Draw();
                ed.WriteMessage("\nLength = {0} Width = {1} Area = {2}", rect.Length, rect.Width, rect.Area);
            }

     

    Gilles Chanteau
    Please use plain text.
    Mentor
    Posts: 214
    Registered: ‎04-11-2010

    Re: Area, Length and Width of last object created

    04-13-2012 07:48 PM in reply to: vince1327

    My shot:

     

    <CommandMethod("DREC")> _
        Public Sub DrawRect()
            Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
            Dim db As Database = HostApplicationServices.WorkingDatabase()
            Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
            Dim p1, p2 As Point3d
    
            Using acTrans As Transaction = db.TransactionManager.StartTransaction()
                Dim acSSPrompt As PromptPointResult = doc.Editor.GetPoint("Select First Point: ")
                If acSSPrompt.Status = PromptStatus.OK Then
                    p1 = acSSPrompt.Value
                    acSSPrompt = doc.Editor.GetCorner(vbCrLf + "Select Second Point: ", p1)
                    If acSSPrompt.Status = PromptStatus.OK Then
                        p2 = acSSPrompt.Value
                    Else
                        MsgBox("Invalid point")
                        Exit Sub
                    End If
                Else
                    MsgBox("Invalid point")
                    Exit Sub
                End If
    
                Dim v1 As Vector3d
                Dim theta As Double
                Dim p3, p4 As Point2D
                Dim a, b, l, s As Double
                Dim d As Double
    
                v1 = p1.GetVectorTo(p2)
                theta = v1.GetAngleTo(Vector3d.XAxis, Vector3d.ZAxis.Negate())
                d = p1.DistanceTo(p2)
                a = d * Math.Cos(theta)
                b = d * Math.Sin(theta)
                l = 2 * (Math.Abs(a) + Math.Abs(b))
                s = Math.Abs(a * b)
    
                If s <= 0.001 Then
                    MsgBox("Degenerated Rectangle, try again", vbCritical)
                    Exit Sub
                End If
    
                p3 = New Point3d(p1.X + a, p1.Y)
                p4 = New Point3d(p1.X, p1.Y + b)
    
                Dim pl As New Polyline
    
                pl.AddVertexAt(0, New Point2d(p1.X, p1.Y), 0, 0, 0)
                pl.AddVertexAt(1, p3, 0, 0, 0)
                pl.AddVertexAt(2, New Point2d(p2.X, p2.Y), 0, 0, 0)
                pl.AddVertexAt(3, p4, 0, 0, 0)
                pl.Closed = True
    
                Dim acBlkTbl As BlockTable
                acBlkTbl = acTrans.GetObject(db.BlockTableId, OpenMode.ForRead)
                Dim acBlkTblRec As BlockTableRecord
                acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
    
                acBlkTblRec.AppendEntity(pl)
                acTrans.AddNewlyCreatedDBObject(pl, True)
    
                ed.WriteMessage(vbCrLf + "Rectangle length:=" + l.ToString + vbCrLf)
                ed.WriteMessage("Rectangle Area:=" + s.ToString + vbCrLf)
                ed.WriteMessage("Width:=" + Math.Abs(a).ToString + vbCrLf)
                ed.WriteMessage("Height:=" + Math.Abs(b).ToString + vbCrLf)
    
                acTrans.Commit()
            End Using
        End Sub

     

    Please use plain text.
    Distinguished Contributor
    vince1327
    Posts: 117
    Registered: ‎11-02-2011

    Re: Area, Length and Width of last object created

    04-16-2012 06:50 AM in reply to: _gile

    Thanks to everyone for their input! _gile thank you very much, with your example i got it working perfectly, much appreciated!!!!

    Please use plain text.