perlon

[C#] Klasa DrawJig i justowanie obiektów DBText

Recommended Posts

Witam.

Chciałbym zaprezentować przykładowy kod do wstawiania obiektów do rysunku z podglądem tego co zostanie wstawione. Rozwiązanie oparte o klasę JigDraw. Starałem się maksymalnie skrócić kod usuwając bloki try catch oraz wstawiając tylko jedną entycję. Z powodzeniem można go jednak przerobić zastępując Typ Entity typem IEnumerable<Entity> i wstawiać całe zespoły obiektów.

Mam jednak pewną zagwostkę dla pary klas jak w temacie. Poniżej kod wstawiający obiekt klasy DBText z justifikacją LeftCenter uzyskaną za pomocą:   

tx1.VerticalMode = TextVerticalMode.TextVerticalMid;

Najpierw efekt którego nie chcę:

jig.thumb.gif.f243449dacb02b5a6723bc8bcd9fc8b9.gif

Kompletny kod który to realizuje:

using ZwSoft.ZwCAD.DatabaseServices;
using ZwSoft.ZwCAD.EditorInput;
using ZwSoft.ZwCAD.Geometry;
using ZwSoft.ZwCAD.GraphicsInterface;
using ZwSoft.ZwCAD.ApplicationServices;
using ZwSoft.ZwCAD.Runtime;

namespace JigTest
{

    public class Jig : DrawJig
    {
        private readonly Point3d basePoint;
        private readonly Entity entity;
        private Point3d currentPoint;
        private Matrix3d transformation;

        public Jig(Entity txt, Point3d point) : base()
        {
            entity = txt;
            basePoint = point;
        }

        public Entity GetEntity()
        {
            var result = entity.Clone() as DBText;
            result.TransformBy(transformation);

            return result;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            JigPromptPointOptions jigOpt = new JigPromptPointOptions("Wskaż punkt wstawienia:")
            {
                UserInputControls = UserInputControls.Accept3dCoordinates,
                BasePoint = basePoint
            };
            PromptPointResult res = prompts.AcquirePoint(jigOpt);
            currentPoint = res.Value;
            return SamplerStatus.OK;
        }

        protected override bool WorldDraw(WorldDraw draw)
        {
            transformation = Matrix3d.Displacement(basePoint.GetVectorTo(currentPoint));
            var geometry = draw.Geometry;
            if (geometry != null)
            {
                geometry.PushModelTransform(transformation);
                geometry.Draw(entity);
            }
            return true;
        }
    }

    public class JigCommands
    {
        [CommandMethod("JIG")]
        public void Jig()
        {
            try
            {
                var tx1 = new DBText();
                tx1.SetDatabaseDefaults();
                tx1.TextStyle = Application.DocumentManager.MdiActiveDocument.Database.Textstyle;
                tx1.Height = 2;
                tx1.Position = new Point3d(0, 0, 0);
                tx1.TextString = "Tekst";
                tx1.VerticalMode = TextVerticalMode.TextVerticalMid;

                var jig = new Jig(tx1, new Point3d(0, 0, 0));
                Application.DocumentManager.MdiActiveDocument.Editor.Drag(jig);
                var ent = jig.GetEntity();
                SaveToDatabase(ent);
            }
            catch(Exception ex)
            {
                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
            }
        }

        public static void SaveToDatabase(Entity ent)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            using (var tr = doc.TransactionManager.StartTransaction())
            {
                var btr = tr.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                btr.AppendEntity(ent);
                tr.AddNewlyCreatedDBObject(ent, true);
                tr.Commit();
            }
        }
    }
}

Jak widać obiekt DBText przed wstawieniem do bazy rysunku ignoruje ustawienie TextVerticalMode. W trakcje wybory miejsca wstawienia ma osadzenie domyślne LeftBottom. Po zapisaniu encji do bazy rysunku dopasowanie jest respektowane i obiekt jest wyświetlany prawidłowo LeftCenter. Rozwiązaniem jest przed przekazaniem do klasy Jig obiektu uprzednio zapisanego do bazy a następnie usunięcie go z bazy przed wywołaniem metody Drag()

        [CommandMethod("JIG")]
        public void Jig()
        {
            try
            {
                var tx1 = new DBText();
                tx1.SetDatabaseDefaults();
                tx1.TextStyle = Application.DocumentManager.MdiActiveDocument.Database.Textstyle;
                tx1.Height = 2;
                tx1.Position = new Point3d(0, 0, 0);
                tx1.TextString = "Tekst";
                tx1.VerticalMode = TextVerticalMode.TextVerticalMid;
                SaveToDatabase(tx1);

                var jig = new Jig(tx1, new Point3d(0, 0, 0));
                EraseFromDatabase(tx1);
                Application.DocumentManager.MdiActiveDocument.Editor.Drag(jig);
                var ent = jig.GetEntity();
                SaveToDatabase(ent);
            }
            catch(Exception ex)
            {
                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
            }
        }

        public static void EraseFromDatabase(Entity ent)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            using (var tr = doc.TransactionManager.StartTransaction())
            {
                ent.ObjectId.GetObject(OpenMode.ForWrite).Erase(true);
                tr.Commit();
            }
        }

Efekt jest prawidłowy ale metoda wydaje się być nieco na około.

jig1.thumb.gif.01d9f27a10365eb1d9f5f88ec46387d6.gif

Na koniec pytanie:

Czy jest jakiś elegancji sposób aby metoda geometry.Draw(entity) wołana w metodzie WorlDraw klasy Jig respektowała właściwości obiekty typu DBText zanim ten obiekt zostanie utrwalony w bazie rysunku?

Share this post


Link to post
Share on other sites

Wygląda na to, że nie trzeba dodawać, usuwać i przesuwać.
Wystarczy dodać do bazy, otworzyć do zapisu i będzie OK.
Twój kod przerobiłbym tak:

using ZwSoft.ZwCAD.DatabaseServices;
using ZwSoft.ZwCAD.EditorInput;
using ZwSoft.ZwCAD.Geometry;
using ZwSoft.ZwCAD.GraphicsInterface;
using ZwSoft.ZwCAD.ApplicationServices;
using ZwSoft.ZwCAD.Runtime;

namespace JigTest
{

    public class Jig : DrawJig
    {
        private readonly Point3d basePoint;
        private readonly Entity entity;
        private Point3d currentPoint;
        public Matrix3d transformation;

        
        public Jig(Entity txt, Point3d point)
            : base()
        {
            entity = txt;
            basePoint = point;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            JigPromptPointOptions jigOpt = new JigPromptPointOptions("Wskaż punkt wstawienia:")
            {
                UserInputControls = UserInputControls.Accept3dCoordinates,
                BasePoint = basePoint
            };
            PromptPointResult res = prompts.AcquirePoint(jigOpt);
            currentPoint = res.Value;
            return SamplerStatus.OK;
        }

        protected override bool WorldDraw(WorldDraw draw)
        {
            transformation = Matrix3d.Displacement(basePoint.GetVectorTo(currentPoint));
            var geometry = draw.Geometry;
            if (geometry != null)
            {
                geometry.PushModelTransform(transformation);
                geometry.Draw(entity);
            }
            return true;
        }
    }

    public class JigCommands
    {
        [CommandMethod("JIG")]
        public void Jig()
        {
            try
            {
                var tx1 = new DBText();
                tx1.SetDatabaseDefaults();
                tx1.TextStyle = Application.DocumentManager.MdiActiveDocument.Database.Textstyle;
                tx1.Height = 2;
                tx1.Position = new Point3d(0, 0, 0);
                tx1.TextString = "Tekst";
                tx1.VerticalMode = TextVerticalMode.TextVerticalMid;

                SaveToDatabase(tx1);

                Document doc = Application.DocumentManager.MdiActiveDocument;
                using (var tr = doc.TransactionManager.StartTransaction())
                {
                    var txt = tr.GetObject(tx1.Id, OpenMode.ForWrite) as DBText;
                    var jig = new Jig(txt, new Point3d(0, 0, 0));
                    Application.DocumentManager.MdiActiveDocument.Editor.Drag(jig);
                    txt.TransformBy(jig.transformation);
                    tr.Commit();
                }
            }
            catch (Exception ex)
            {
                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
            }
        }

        public static void SaveToDatabase(Entity ent)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            using (var tr = doc.TransactionManager.StartTransaction())
            {
                var btr = tr.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                btr.AppendEntity(ent);
                tr.AddNewlyCreatedDBObject(ent, true);
                tr.Commit();
            }
        }
    }
}

Choć zaznaczam, że wcale nie czuję się tu jakoś bardzo kompetentny.

Share this post


Link to post
Share on other sites

Kontekst powyższego jest nieco szerszy, ale nie chciałem zbyt komplikować kodu. W szczególności chciałem wstawiać do rysunku blok z atrybutem lub opcjonalnie encje w grupie mając w jig'u obraz takiego bloku/grupy. W ogólnym przypadku chciałem coś innego mieć na podglądzie a co innego ostatecznie wstawiać do rysunku. Stąd poszukiwania prawidłowej reprezentacji graficznej bez faktycznego wstawiania do bazy rysunku. Wygląda jednak, że chyba się nie da uzyskać 100% reprezentacji graficznej obiektu bez jego wstawienia do bazy. Ostatecznie chyba przeniosę zapis do rysunku do wnętrza klasy Jig

        public Jig(Entity txt, Point3d point) : base()
        {
            entity = txt;
            basePoint = point;
            Prepare();
        }

        private void Prepare()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            using (var tr = doc.TransactionManager.StartTransaction())
            {
                var btr = tr.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                btr.AppendEntity(entity);
                tr.AddNewlyCreatedDBObject(entity, true);
                entity.Erase();
                tr.Commit();
            }
        }

co uprości nieco wywołanie

        [CommandMethod("JIG")]
        public void Jig()
        {
            try
            {
                var tx1 = new DBText();
                tx1.SetDatabaseDefaults();
                tx1.Height = 2;
                tx1.Position = new Point3d(0, 0, 0);
                tx1.TextString = "Tekst";
                tx1.VerticalMode = TextVerticalMode.TextVerticalMid;

                var jig = new Jig(tx1, new Point3d(0, 0, 0));
                var result = Application.DocumentManager.MdiActiveDocument.Editor.Drag(jig);
                if(result.Status == PromptStatus.OK)
                {
                    SaveToDatabase(jig.GetEntity());
                }
            }
            catch(Exception ex)
            {
                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
            }
        }

Powyższe trzeba jeszcze uzupełnić o kontrolę czy obiekt aktualnie jest w bazie czy nie i jeden lub dwa try catch'e i da to kod całkiem uniwersalny

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now