Layout Create

Layout Create

k005
Advisor Advisor
695 Views
8 Replies
Message 1 of 9

Layout Create

k005
Advisor
Advisor

Hello friends,


With this code, I create layout. But there is a problem ...


Viewport Size Not at P2 points with P1 ..! How can I fix this?


I want; The formation of a single layout-viewport by point P1 and P2. . P1 and P2 in size.

 

 

 [CommandMethod("LCT")]
 public void LayoutCreate()
 {
     var (_, db, ed) = GetActiveDocumentComponents();

     var p1 = ed.GetPoint("\nP1 noktası: ").Value;
     var p2 = ed.GetPoint("\nP2 noktası: ").Value;

     ed.Command("_.ZOOM", "_W", p1, p2);

     var name = ed.GetString("\nLayout ismi: ").StringResult;

     using (var tr = db.TransactionManager.StartTransaction())
     {
         var lm = LayoutManager.Current;
         lm.CreateLayout(name);
         lm.CurrentLayout = name;

         var layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
         var layout = (Layout)tr.GetObject((ObjectId)layoutDict[name], OpenMode.ForWrite);
         var btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);

         var toErase = new List<ObjectId>();
         foreach (ObjectId id in btr)
         {
             if (tr.GetObject(id, OpenMode.ForRead) is Autodesk.AutoCAD.DatabaseServices.Viewport)
                 toErase.Add(id);
         }
         foreach (var id in toErase)
         {
             var vpOld = (Autodesk.AutoCAD.DatabaseServices.Viewport)tr.GetObject(id, OpenMode.ForWrite);
             vpOld.Erase();
         }

         var vp = new Autodesk.AutoCAD.DatabaseServices.Viewport();
         vp.SetDatabaseDefaults();
         btr.AppendEntity(vp);
         tr.AddNewlyCreatedDBObject(vp, true);

         vp.On = true;
         vp.ViewCenter = new Point2d((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2);
         vp.ViewHeight = Math.Abs(p2.Y - p1.Y);
         vp.Width = Math.Abs(p2.X - p1.X);
         vp.Height = Math.Abs(p2.Y - p1.Y);
         vp.CenterPoint = new Point3d(vp.Width / 2, vp.Height / 2, 0);
         tr.Commit();
     }
 }

 

0 Likes
Accepted solutions (1)
696 Views
8 Replies
Replies (8)
Message 2 of 9

norman.yuan
Mentor
Mentor

It is not very clear what your question is about.

 

1. You created a Layout without explicitly configuring its PlotSettings, so it is not clear if the Viewport not being positioned within the paper size is your issue?

2. Are the 2 points picked is the REAL points you want on the new layout? If they are, then you may have to configure the layout's PlotSettings to a proper paper size to cover the 2 points.

3. Since you ask user to select the 2 points before the layout is created, so, the 2 points' value is based on the current space (possibly, ModelSpace), so you may have to transform them properly according to the new layout. One way to save from the point transformation is to create the new layout first and set it as current, then ask user to select points (thus the points are selected on the new layout, then create the viewport.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 9

k005
Advisor
Advisor

I add a picture ...

 

2. The picture shows the desired situation. ( After )

 

2025-08-10_170151.jpg

0 Likes
Message 4 of 9

_gile
Consultant
Consultant

Still not clear...

Anyway, as @norman.yuan said, to set the view (zoom) in the newly created viewport, you have to convert the coordinates got from the user in model space UCS to WCS and then, from WCS to the viewport DCS.

Here's a example adapted from your code which uses an extension method from the GeometryExtensions library.

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using System;

[assembly: CommandClass(typeof(CreateLayoutAndViewportSample.Commands))]

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

            // Prompt the user to get points
            var promptPointResult = ed.GetPoint("\nFirst corner: ");
            if (promptPointResult.Status != PromptStatus.OK)
                return;
            var ucsPt1 = promptPointResult.Value;

            promptPointResult = ed.GetCorner("\nOpposite corner: ", ucsPt1);
            if (promptPointResult.Status != PromptStatus.OK)
                return;
            var ucsPt2 = promptPointResult.Value;

            // Prompt the user for the Layout name
            var promptResult = ed.GetString("\nLayout name");
            if (promptResult.Status != PromptStatus.OK)
                return;
            string layoutName = promptResult.StringResult;

            var layoutManager = LayoutManager.Current;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                // Delete the layout if it already exists
                var layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                if (layoutDict.Contains(layoutName))
                    layoutManager.DeleteLayout(layoutName);

                // Create a new Layout
                var layoutId = layoutManager.CreateLayout(layoutName);
                layoutManager.CurrentLayout = layoutName;

                // Create a Viewport
                var vp = new Viewport();
                vp.SetDatabaseDefaults();
                var wcsPt1 = ucsPt1.TransformBy(ed.CurrentUserCoordinateSystem);
                var wcsPt2 = ucsPt2.TransformBy(ed.CurrentUserCoordinateSystem);
                vp.CenterPoint = new LineSegment3d(wcsPt1, wcsPt2).MidPoint;
                vp.Width = Math.Abs(wcsPt1.X - wcsPt2.X);
                vp.Height = Math.Abs(wcsPt1.Y - wcsPt2.Y);

                var layout = (Layout)tr.GetObject(layoutId, OpenMode.ForRead);
                var btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);
                btr.AppendEntity(vp);
                tr.AddNewlyCreatedDBObject(vp, true);

                // Set the viewport view
                vp.On = true;
                var dcsPt1 = wcsPt1.TransformBy(vp.WCS2DCS());
                var dcsPt2 = wcsPt2.TransformBy(vp.WCS2DCS());
                vp.ViewCenter = new Point2d((dcsPt1.X + dcsPt2.X) * 0.5, (dcsPt1.Y + dcsPt2.Y) * 0.5);
                vp.ViewHeight = Math.Abs(dcsPt1.Y - dcsPt2.Y);
                tr.Commit();
            }
        }
    }
    // Extract from https://github.com/gileCAD/GeometryExtensions
    public static class Extension
    {
        /// <summary>
        /// Gets the transformation matrix of the world coordinate system (WCS)
        /// to the display coordinate system (DCS) of the specified window.
        /// </summary>
        /// <param name="viewport">The instance to which this method applies.</param>
        /// <returns>The transformation matrix from WCS to DCS.</returns>
        /// <exception cref="System.ArgumentNullException">ArgumentException is thrown if <paramref name="viewport"/> is null.</exception>
        public static Matrix3d WCS2DCS(this Viewport viewport)
        {
            if (viewport is null)
                throw new System.ArgumentNullException(nameof(viewport));
            return
                Matrix3d.WorldToPlane(viewport.ViewDirection) *
                Matrix3d.Displacement(viewport.ViewTarget.GetAsVector().Negate()) *
                Matrix3d.Rotation(viewport.TwistAngle, viewport.ViewDirection, viewport.ViewTarget);
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 9

k005
Advisor
Advisor

 

I applied the code you gave a little by changing it. But this is not the result I still want.

 

[CommandMethod("LCT2", CommandFlags.NoPaperSpace)]
public void Test()
{
    var (_, db, ed) = GetActiveDocumentComponents();

    // Prompt the user to get points
    var promptPointResult = ed.GetPoint("\nFirst corner: ");
    if (promptPointResult.Status != PromptStatus.OK)
        return;
    var ucsPt1 = promptPointResult.Value;

    promptPointResult = ed.GetCorner("\nOpposite corner: ", ucsPt1);
    if (promptPointResult.Status != PromptStatus.OK)
        return;
    var ucsPt2 = promptPointResult.Value;

    // Prompt the user for the Layout name
    var promptResult = ed.GetString("\nLayout name");
    if (promptResult.Status != PromptStatus.OK)
        return;
    string layoutName = promptResult.StringResult;

    var layoutManager = LayoutManager.Current;

    using (var tr = db.TransactionManager.StartTransaction())
    {
        // Delete the layout if it already exists
        var layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
        if (layoutDict.Contains(layoutName))
            layoutManager.DeleteLayout(layoutName);

        // Create a new Layout
        var layoutId = layoutManager.CreateLayout(layoutName);
        layoutManager.CurrentLayout = layoutName;

        // Create a Viewport
        var vp = new Autodesk.AutoCAD.DatabaseServices.Viewport();
        vp.SetDatabaseDefaults();
        var wcsPt1 = ucsPt1.TransformBy(ed.CurrentUserCoordinateSystem);
        var wcsPt2 = ucsPt2.TransformBy(ed.CurrentUserCoordinateSystem);
        //vp.CenterPoint = new LineSegment3d(wcsPt1, wcsPt2).MidPoint;
        vp.Width = Math.Abs(wcsPt1.X - wcsPt2.X);
        vp.Height = Math.Abs(wcsPt1.Y - wcsPt2.Y);
        vp.CenterPoint = new Point3d(vp.Width / 2, vp.Height / 2, 0);

        var layout = (Layout)tr.GetObject(layoutId, OpenMode.ForRead);
        var btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);
        btr.AppendEntity(vp);
        tr.AddNewlyCreatedDBObject(vp, true);

        // Set the viewport view
        vp.On = true;
        var dcsPt1 = wcsPt1.TransformBy(vp.WCS2DCS());
        var dcsPt2 = wcsPt2.TransformBy(vp.WCS2DCS());
        //vp.ViewCenter = new Point2d((dcsPt1.X + dcsPt2.X) * 0.5, (dcsPt1.Y + dcsPt2.Y) * 0.5);
        vp.ViewCenter = new Point2d((dcsPt1.X + dcsPt2.X) / 2, (dcsPt1.Y + dcsPt2.Y) / 2);
        vp.ViewHeight = Math.Abs(dcsPt1.Y - dcsPt2.Y);
        tr.Commit();
    }
}

This is the result I get .. Add Picture.

 

END01.jpg

****  There will be no lower left part appearing in the picture. This will cover the P1 and P2 point ... So only the white part will appear. But in P1 and P2 size. The gray place that appears in the picture on the screen right now will look white ...

 

0 Likes
Message 6 of 9

_gile
Consultant
Consultant

Still not sure to fully understand the request.

This one creates a new layout and a viewport which fills the (default) plotting area and center and zoom the view so that the input rectangle are within the viewport.

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

    // Prompt the user to get points
    var promptPointResult = ed.GetPoint("\nFirst corner: ");
    if (promptPointResult.Status != PromptStatus.OK)
        return;
    var ucsPt1 = promptPointResult.Value;

    promptPointResult = ed.GetCorner("\nOpposite corner: ", ucsPt1);
    if (promptPointResult.Status != PromptStatus.OK)
        return;
    var ucsPt2 = promptPointResult.Value;

    // Prompt the user for the Layout name
    var promptResult = ed.GetString("\nLayout name");
    if (promptResult.Status != PromptStatus.OK)
        return;
    string layoutName = promptResult.StringResult;

    var layoutManager = LayoutManager.Current;

    using (var tr = db.TransactionManager.StartTransaction())
    {
        // Delete the layout if it already exists
        var layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
        if (layoutDict.Contains(layoutName))
            layoutManager.DeleteLayout(layoutName);

    // Save and disable LAYOUTCREATEVIEWPORT system variable
    object layoutCreateViewport = Application.GetSystemVariable("LAYOUTCREATEVIEWPORT");
    Application.SetSystemVariable("LAYOUTCREATEVIEWPORT", 0);

        // Create a new Layout (default settings)
        try
        {
            var layoutId = layoutManager.CreateLayout(layoutName);
            layoutManager.CurrentLayout = layoutName;
            var layout = (Layout)tr.GetObject(layoutId, OpenMode.ForRead);
            var btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);

            // Create a Viewport which fits the printable area
            var minPoint = layout.PlotPaperMargins.MinPoint;
            var maxPoint = layout.PlotPaperMargins.MaxPoint;
            var paperSize = layout.PlotPaperSize;
            bool landscape =
                layout.PlotRotation == PlotRotation.Degrees000 ||
                layout.PlotRotation == PlotRotation.Degrees180;
            double viewportWidth =
                landscape ? paperSize.X - maxPoint.X - minPoint.X : paperSize.Y - maxPoint.Y - minPoint.Y;
            double viewportHeight =
                landscape ? paperSize.Y - maxPoint.Y - minPoint.Y : paperSize.X - maxPoint.X - minPoint.X;
            var viewportCenter = new Point3d(viewportWidth * 0.5, viewportHeight * 0.5, 0.0);

            var vp = new Viewport();
            vp.CenterPoint = viewportCenter;
            vp.Width = viewportWidth;
            vp.Height = viewportHeight;
            btr.AppendEntity(vp);
            tr.AddNewlyCreatedDBObject(vp, true);
            vp.On = true;

            // Set the viewport view (center and height) according to model space input points
            var wcsPt1 = ucsPt1.TransformBy(ed.CurrentUserCoordinateSystem);
            var wcsPt2 = ucsPt2.TransformBy(ed.CurrentUserCoordinateSystem);
            var dcsPt1 = wcsPt1.TransformBy(vp.WCS2DCS());
            var dcsPt2 = wcsPt2.TransformBy(vp.WCS2DCS());
            double viewWidth = Math.Abs(dcsPt1.X - dcsPt2.X);
            double viewHeight = Math.Abs(dcsPt1.Y - dcsPt2.Y);
            vp.ViewCenter = new Point2d((dcsPt1.X + dcsPt2.X) * 0.5, (dcsPt1.Y + dcsPt2.Y) * 0.5);
            double ratio = (viewportHeight / viewportWidth) / (viewHeight / viewWidth);
            vp.ViewHeight = ratio <= 1 ? viewHeight : viewHeight * ratio;

            tr.Commit();
        }
        catch (System.Exception ex)
        {
            ed.WriteMessage($"\nError: {ex.Message}");
        }
        finally
        {
            Application.SetSystemVariable("LAYOUTCREATEVIEWPORT", layoutCreateViewport);
        }
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 9

k005
Advisor
Advisor

This is not an Autocad part that I use very much ... That's why I can't tell you exactly ... I will find the missing parts and write again here.

 

Thank you, Master. @_gile 

0 Likes
Message 8 of 9

_gile
Consultant
Consultant
Accepted solution

Another example that creates a viewport with the same height/width ratio as the input rectangle inside of the printable area.

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

    var ucs = ed.CurrentUserCoordinateSystem;

    // Prompt the user to get points
    var promptPointResult = ed.GetPoint("\nFirst corner: ");
    if (promptPointResult.Status != PromptStatus.OK)
        return;
    var wcsPt1 = promptPointResult.Value.TransformBy(ucs);

    promptPointResult = ed.GetCorner("\nOpposite corner: ", promptPointResult.Value);
    if (promptPointResult.Status != PromptStatus.OK)
        return;
    var wcsPt2 = promptPointResult.Value.TransformBy(ucs);

    // Prompt the user for the Layout name
    var promptResult = ed.GetString("\nLayout name");
    if (promptResult.Status != PromptStatus.OK)
        return;
    string layoutName = promptResult.StringResult;

    var layoutManager = LayoutManager.Current;

    using (var tr = db.TransactionManager.StartTransaction())
    {
        // Delete the layout if it already exists
        var layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
        if (layoutDict.Contains(layoutName))
            layoutManager.DeleteLayout(layoutName);

        // Save and disable LAYOUTCREATEVIEWPORT system variable
        object layoutCreateViewport = Application.GetSystemVariable("LAYOUTCREATEVIEWPORT");
        Application.SetSystemVariable("LAYOUTCREATEVIEWPORT", 0);

        // Create a new Layout (default settings)
        try
        {
            var layoutId = layoutManager.CreateLayout(layoutName);
            layoutManager.CurrentLayout = layoutName;
            var layout = (Layout)tr.GetObject(layoutId, OpenMode.ForRead);
            var btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite);

            // Create a viewport with the same height/width ratio as the input rectangle
            // that fills the printable area
            var minPoint = layout.PlotPaperMargins.MinPoint;
            var maxPoint = layout.PlotPaperMargins.MaxPoint;
            var paperSize = layout.PlotPaperSize;
            bool landscape =
                layout.PlotRotation == PlotRotation.Degrees000 ||
                layout.PlotRotation == PlotRotation.Degrees180;
            double paperWidth =
                landscape ? paperSize.X - maxPoint.X - minPoint.X : paperSize.Y - maxPoint.Y - minPoint.Y;
            double paperHeight =
                landscape ? paperSize.Y - maxPoint.Y - minPoint.Y : paperSize.X - maxPoint.X - minPoint.X;

            double viewWidth = Math.Abs(wcsPt1.X - wcsPt2.X);
            double viewHeight = Math.Abs(wcsPt1.Y - wcsPt2.Y);
            double ratio = (paperHeight / paperWidth) / (viewHeight / viewWidth);

            var vp = new Viewport();
            vp.CenterPoint = new Point3d(paperWidth * 0.5, paperHeight * 0.5, 0.0);
            if (ratio <= 1)
            {
                vp.Height = paperHeight;
                vp.Width = paperWidth * ratio;
            }
            else
            {
                vp.Width = paperWidth;
                vp.Height = paperHeight / ratio;
            }
                btr.AppendEntity(vp);
            tr.AddNewlyCreatedDBObject(vp, true);
            vp.On = true;

            // Set the viewport view (center and height) according to model space input points
            var dcsPt1 = wcsPt1.TransformBy(vp.WCS2DCS());
            var dcsPt2 = wcsPt2.TransformBy(vp.WCS2DCS());
            vp.ViewCenter = new Point2d((dcsPt1.X + dcsPt2.X) * 0.5, (dcsPt1.Y + dcsPt2.Y) * 0.5);
            vp.ViewHeight = viewHeight;

            tr.Commit();
        }
        catch (System.Exception ex)
        {
            ed.WriteMessage($"\nError: {ex.Message}");
        }
        finally
        {
            Application.SetSystemVariable("LAYOUTCREATEVIEWPORT", layoutCreateViewport);
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 9 of 9

k005
Advisor
Advisor

Yes.! That's what I want. Thank you very much. 🤗  Health Master.@_gile 

0 Likes