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


Rekomendowane odpowiedzi

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?

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

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

Odnośnik do komentarza
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie