.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Problem with Retrieving Objects from Layout

2 REPLIES 2
SOLVED
Reply
Message 1 of 3
adam_luER5XJ
165 Views, 2 Replies

Problem with Retrieving Objects from Layout

I'm trying to extract a portion of objects from the model space using a layout (paper space) without modifying the model itself.

However, my program can only retrieve two viewports instead of the actual objects. Can someone please point out where I might be going wrong? Thank you.

 

Here's my code:
The code also attempts to retrieve objects using the viewport coordinates, but it still fails to get the actual objects.

 

[CommandMethod("ShowLayoutObject")]
public void ShowLayoutObject()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    Editor ed = doc.Editor;

    string layoutName = "Layout3";

    using (Transaction trans = db.TransactionManager.StartTransaction())
    {
        DBDictionary layoutsDict = trans.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;

        if (layoutsDict.Contains(layoutName))
        {
            Layout layout = layoutsDict.GetAt(layoutName).GetObject(OpenMode.ForRead) as Layout;
            BlockTableRecord btr = trans.GetObject(layout.BlockTableRecordId, OpenMode.ForRead) as BlockTableRecord;

            foreach (ObjectId id in btr)
            {
                Entity ent = trans.GetObject(id, OpenMode.ForRead) as Entity;
                if (ent != null)
                {
                    ed.WriteMessage($"\nFind Object. Type: {ent.GetType().Name}, ObjectId: {ent.ObjectId}");
                    if (ent is Viewport)
                    {
                        Viewport vp = (Viewport)ent;
                        Extents3d viewportExtents = vp.GeometricExtents;
                        if (viewportExtents == null) continue;

                        PromptSelectionResult psr = ed.SelectWindow(viewportExtents.MinPoint, viewportExtents.MaxPoint);
                        if (psr.Status != PromptStatus.OK)
                        {
                            ed.WriteMessage("\nNo Selected Object");
                            continue;
                        }

                        SelectionSet ss = psr.Value;
                        foreach (ObjectId oID in ss.GetObjectIds())
                        {
                            Entity sourceEntity = (Entity)trans.GetObject(oID, OpenMode.ForRead);
                            ed.WriteMessage($"\nObject Type: {ent.GetType().Name}, ObjectId: {ent.ObjectId}");
                        }
                    }
                }
            }
        }
    }
}

 


I'm not sure if I'm creating the layout incorrectly. Here's how I'm doing it:
I'm new to this, so I'll try my best to describe it.
I open a .dwg file provided by someone else in AutoCAD and click "New Layout". A new layout is created on the screen, and all objects from the model space are brought into the layout.
There's a dashed box on the screen. According to online information, this should be the print area. There's also a solid box, which I think is the visible area.
Then I execute the command ".MSPACE", zoom in to the objects I want to extract within the solid box using the mouse wheel, and then execute the command ".PSPACE". Finally, I save the file.

2 REPLIES 2
Message 2 of 3
_gile
in reply to: adam_luER5XJ

Hi,

To be able to select model space entities using  a paper space viewport coordinates, you have to convert these coordinates from the paper space display coordinate system (PSDCS) into the the model space current user coordinate system (UCS) which is used by the Editor.Select methods.

Here's an example using some extension methods which only works with polygonal viewports.

 

Extension methods:

 

public static class Extension
{

    public static Matrix3d PSDCS2DCS(this Viewport vp)
    {
        return
            Matrix3d.Displacement(vp.CenterPoint.GetVectorTo(vp.ViewCenter.Convert3d())) *
            Matrix3d.Scaling(1.0 / vp.CustomScale, vp.CenterPoint);
    }

    public static Matrix3d DCS2WCS(this Viewport vp)
    {
        return
            Matrix3d.Rotation(-vp.TwistAngle, vp.ViewDirection, vp.ViewTarget) *
            Matrix3d.Displacement(vp.ViewTarget.GetAsVector()) *
            Matrix3d.PlaneToWorld(vp.ViewDirection);
    }

    public static IEnumerable<Point3d> GetViewportPsdcsPolygon(this Viewport vp)
    {
        if (vp.NonRectClipOn)
        {
            if (vp.NonRectClipEntityId.ObjectClass.Name == "AcDbPolyline")
            {
                var pline = (Polyline)vp.NonRectClipEntityId.GetObject(OpenMode.ForRead);
                if (pline.HasBulges)
                {
                    throw new NotImplementedException();
                }
                else
                {
                    for (int i = 0; i < pline.NumberOfVertices; i++)
                    {
                        yield return pline.GetPoint3dAt(i);
                    }
                }
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        else
        {
            var center = vp.CenterPoint;
            double h = vp.Height * 0.5;
            double w = vp.Width * 0.5;
            yield return new Point3d(center.X - w, center.Y - h, 0.0);
            yield return new Point3d(center.X + w, center.Y - h, 0.0);
            yield return new Point3d(center.X + w, center.Y + h, 0.0);
            yield return new Point3d(center.X - w, center.Y + h, 0.0);
        }
    }

    public static IEnumerable<Point3d> GetViewportWcsBoundary(this Viewport vp)
    {
        var xform = vp.DCS2WCS() * vp.PSDCS2DCS();
        return
            vp.GetViewportPsdcsPolygon()
            .Cast<Point3d>()
            .Select(p => p.TransformBy(xform));
    }

    public static Point3d Convert3d(this Point2d pt) =>
        new Point3d(pt.X, pt.Y, 0.0);
}

 

 

A testing command (must be called from model space tab)

 

[CommandMethod("TEST", CommandFlags.NoPaperSpace)]
public void Test()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;

    string layoutName = "Layout3";

    using (var tr = db.TransactionManager.StartTransaction())
    {
        var layouts = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
        if (!layouts.Contains(layoutName))
        {
            ed.WriteMessage($"\nLayout {layoutName} not found.");
            return;
        }
        var layout = (Layout)tr.GetObject(layouts.GetAt(layoutName), OpenMode.ForRead);
        var paperSpace = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);
        var xform = ed.CurrentUserCoordinateSystem.Inverse();
        var viewports = paperSpace
            .Cast<ObjectId>()
            .Where(id => id.ObjectClass.Name == "AcDbViewport")
            .Skip(1);
        foreach (ObjectId id in viewports)
        {
            try
            {
                var viewport = (Viewport)tr.GetObject(id, OpenMode.ForRead);
                var polygon = new Point3dCollection(
                    viewport.GetViewportWcsBoundary()
                    .Select(p => p.TransformBy(xform))
                    .ToArray());
                var selection = ed.SelectWindowPolygon(polygon);
                if (selection.Status == PromptStatus.OK)
                {
                    ed.WriteMessage($"\nViewport {id}");
                    foreach (ObjectId oId in selection.Value.GetObjectIds())
                    {
                        ed.WriteMessage($"\n\tObject Type: {oId.ObjectClass.Name}, ObjectId: {oId}");
                    }
                }
            }
            catch(System.Exception ex)
            {
                ed.WriteMessage($"\nViewport {id}\n\tError: {ex.Message}");
            }
        }
        tr.Commit();
    }
}

 

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 3
adam_luER5XJ
in reply to: _gile

Thank you for answering my question and providing the code. I ran the code and it worked like a charm.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Forma Design Contest


Autodesk Design & Make Report