Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - (gile)

Pages: 1 ... 3 4 [5] 6
61
Blocks / Re: Erase doubled block references
« on: November 26, 2010, 03:06:58 PM »
As this topic became a kind of challenge at TheSwamp, you can find some other solutions there (using Linq for example).

It also appears that using List<T> seems to be much more time expansive than Dictionary<key,value> while seaching an item (even if never mind of the value).

So, in the upper code, replacing:

List<DuplicatePattern> with Dictionary<DuplicatePattern, int>

Patterns.Contains(dp) with Patterns.ContainsKey(db)

Patterns.Add(dp) with Patterns.Add(dp, 0)

should increase the execution speed.

62
Blocks / Re: Erase doubled block references
« on: November 25, 2010, 01:44:33 PM »
Sorry, no need to use a ResultBuffer and it seems to be faster using a SelectionSet

Here's a new way:
Code: [Select]
        struct DuplicatePattern
        {
            public string Name;
            public string Layer;
            public ObjectId OwnerId;
            public double PositionX;
            public double PositionY;
            public double PositionZ;
            public double Rotation;
            public double ScaleX;
            public double ScaleY;
            public double ScaleZ;
        }

        private int DeleteDuplicatedBlockRef()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            int result = 0;
            SelectionFilter filter = new SelectionFilter(new TypedValue[1] { new TypedValue(0, "INSERT") });
            PromptSelectionResult psr = ed.SelectAll(filter);
            if (psr.Status != PromptStatus.OK)
                return 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                List<DuplicatePattern> Patterns = new List<DuplicatePattern>();
                foreach (ObjectId id in psr.Value.GetObjectIds())
                {
                    BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead, false);
                    DuplicatePattern dp = new DuplicatePattern();
                    dp.OwnerId = br.OwnerId;
                    dp.Name = br.Name;
                    dp.Layer = br.Layer;
                    dp.PositionX = Math.Round(br.Position.X, 6);
                    dp.PositionY = Math.Round(br.Position.Y, 6);
                    dp.PositionZ = Math.Round(br.Position.Z, 6);
                    dp.Rotation = Math.Round(br.Rotation, 6);
                    dp.ScaleX = Math.Round(br.ScaleFactors.X, 6);
                    dp.ScaleY = Math.Round(br.ScaleFactors.Y, 6);
                    dp.ScaleZ = Math.Round(br.ScaleFactors.Z, 6);
                    if (Patterns.Contains(dp))
                    {
                        br.UpgradeOpen();
                        br.Erase();
                        result++;
                    }
                    else
                        Patterns.Add(dp);
                }
                tr.Commit();
            }
            return result;
        }

63
Blocks / Re: Erase doubled block references
« on: November 24, 2010, 08:32:38 PM »
With the hel of kaefer (@TheSwamp), I learned some functions of the F# Seq module (IEnumerable) which made me able to rewrite a more concise and faster routine.

Code: [Select]
let duplicate (b: BlockReference) =
    b.Name,
    b.OwnerId,
    Math.Round(b.Position.X, 6),
    Math.Round(b.Position.Y, 6),
    Math.Round(b.Position.Z, 6),
    b.Layer,
    Math.Round(b.Rotation, 6),
    Math.Round(b.ScaleFactors.X, 6),
    Math.Round(b.ScaleFactors.Y, 6),
    Math.Round(b.ScaleFactors.Z, 6) 

let deleteDuplicatedBlockRef() =
    let db = HostApplicationServices.WorkingDatabase
    use tr = db.TransactionManager.StartTransaction()

    let getRefs btrId =
        let btr = tr.GetObject(btrId, OpenMode.ForRead) :?> BlockTableRecord
        btr.GetBlockReferenceIds(true, false)
        |> Seq.cast<_>
       
    let openRefs brefId =
        tr.GetObject(brefId, OpenMode.ForRead) :?> BlockReference
       
    let cnt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
              |> Seq.cast<_>
              |> Seq.collect getRefs
              |> Seq.map openRefs
              |> Seq.groupBy duplicate
              |> Seq.collect (fun x -> snd x |> Seq.skip 1)
              |> Seq.fold (fun cnt bref ->
                            bref.UpgradeOpen()
                            bref.Erase()
                            cnt + 1 ) 0
    tr.Commit()
    cnt

64
Layouts and printing / Re: Get the current layout
« on: November 24, 2010, 05:16:16 PM »
As far as I know, while using a 'Using' statement on an object, you don't need to explicitly call dispose. The object should be automatically disposed at the end of the code block  or if an exception is thrown.

With a transaction, all the objects opened with Transaction.GetObject() and the new ones added to the transaction with AddNewlyCreatedDBObject() should be automatically disposed too.
But if an error occurs before 'new' objects are added to the database, they won't be disposed.

If an exception occurs before the transactions is committed, the Dispose() is called by 'Using' and all changes made to database within this transaction are rolled back.

So, in my opinion, the F_GetCurrentLayout method should be like this (no need to Commit the transaction while there were no changes to the Database):
Code: [Select]
Public Function F_GetCurrentLayout() As Layout
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim lm As LayoutManager = LayoutManager.Current
Using tr As Transaction = db.TransactionManager.StartTransaction()
Return DirectCast(tr.GetObject(lm.GetLayoutId(lm.CurrentLayout), OpenMode.ForRead), Layout)
End Using
End Function

To learn more about when and what disposing, you can have a look to this video

65
Blocks / Re: Erase doubled block references
« on: November 24, 2010, 02:54:52 PM »
I think I got something working with the strcture way using a ResultBuffer (the AutoCAD .NET/ObjectARX object which looks the most like a LISP DXF list).

In the following example:
The ParamBlockDoubled are stored in a List<ParamBlockDoubled>, there's no need to use a Dictionary as the items Value (objectId) are never used.
DoubleToErase is defined as a List<BlockReference> because it avoid to open them twice from their ObjectId.
It still uses the BlockTable -> BlockTableRecord _> GetReferenceIds route which avoid to run through the whole database.

Code: [Select]
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace DuplicateTest
{
    public class Commands
    {
        [CommandMethod("Test")]
        public void DelDupBlkRef()
        {
            try
            {
                int del = DeleteDuplicatedBlockRef();
                Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased");
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog("\nError: " + e.Message);
            }
        }

        private int DeleteDuplicatedBlockRef()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            int result = 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                List<ParamBlockDoubled> CollWithoutDouble = new List<ParamBlockDoubled>();
                List<BlockReference> DoubleToErase = new List<BlockReference>();
                foreach (ObjectId id in bt)
                {
                    BlockTableRecord btr =
                        (BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite);
                    ObjectIdCollection idCol = btr.GetBlockReferenceIds(true, false);
                    foreach (ObjectId oId in idCol)
                    {
                        BlockReference br = (BlockReference)tr.GetObject(oId, OpenMode.ForRead, false);
                        ParamBlockDoubled pbd = new ParamBlockDoubled(br);
                        if (!CollWithoutDouble.Contains(pbd))
                            CollWithoutDouble.Add(pbd);
                        else
                            DoubleToErase.Add(br);
                    }
                }
                foreach (BlockReference b in DoubleToErase)
                {
                    b.UpgradeOpen();
                    b.Erase();
                    result ++;
                }
                tr.Commit();
            }
            return result;
        }

        public struct ParamBlockDoubled
        {
            // fields
            public ResultBuffer resBuf;

            // constructor
            public ParamBlockDoubled(BlockReference bRef)
            {
                Point3d pos = new Point3d(
                    Math.Round(bRef.Position.X, 6),
                    Math.Round(bRef.Position.Y, 6),
                    Math.Round(bRef.Position.Z, 6));
                resBuf =
                    new ResultBuffer(
                        new TypedValue[8] {
                            new TypedValue(330, bRef.OwnerId),
                            new TypedValue(2, bRef.Name),
                            new TypedValue(10, pos),
                            new TypedValue(8, bRef.Layer),
                            new TypedValue(50, Math.Round(bRef.Rotation, 6)),
                            new TypedValue(40, Math.Round(bRef.ScaleFactors.X, 6)),
                            new TypedValue(41, Math.Round(bRef.ScaleFactors.Y, 6)),
                            new TypedValue(42, Math.Round(bRef.ScaleFactors.Z, 6))});
            }

            // override method
            public override bool Equals(object obj)
            {
                if (obj.GetType() != typeof(ParamBlockDoubled))
                    return false;
                ParamBlockDoubled pbd = (ParamBlockDoubled)obj;
                return this.resBuf.Equals(pbd.resBuf);
            }

            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }
    }
}

66
Blocks / Re: Erase doubled block references
« on: November 24, 2010, 01:02:33 PM »
1_ Extension methods is a way to add methods to an already existing class. Usually they're compiled in a separate dll so that while this dll is refered by another project, these methods are available the same way as built-in methods.
In the upper example, a 'Duplicate' method is added to the BlockReference class, it's visible in the intellisense as:
Bool BlockReference.Duplicate(BlockReference br).
But as I said, you can define a private method inside your class: Bool Duplicate(BlockReference br1, BlockReference br2).

2_ I really think the structure/GetHashCode... way isn't the simpler one because you have to compare objects with different types (String, Point3d, Double, ...) with tolerances. This way is easy using LISP which allows to build list of different type objects.
The 'for' statement used in the upper example is a classical way to run through collections. It's optimised here by removing the duplicated items from the collection at each loop.

3_ As all functional programming languages, F# provides specific higher order functions to deal with collections (List, Array, Seq) which have none equivalent ones in VB or C#.

67
F# language / Re: Code Converter for F#
« on: November 24, 2010, 08:10:10 AM »
Hi

Never seen one.
F# is really different from C# or VB.net (which are very closed) and it's quite new.

One way to convert should be to get the exe or dll compiled from F# code in CIL and diassemble it with Reflector. But, according to what I tryied the result isn't so good.

68
Blocks / Re: Erase doubled block references
« on: November 23, 2010, 11:15:13 PM »
The Duplicate method can be defined inside the class too, as a private method with 2 arguments.

This is the way used in this F# implementation.

Code: [Select]
module DupBlks

open System
open System.Collections.Generic
open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime

let Duplicate (a: BlockReference) (b: BlockReference) =
    let tol = new Tolerance(1e-6, 1e-6)
    a.Name = b.Name &&
    a.OwnerId = b.OwnerId &&
    a.Position = b.Position &&
    a.Layer = b.Layer &&
    Math.Round(a.Rotation, 5) = Math.Round(b.Rotation, 5) &&
    a.ScaleFactors = b.ScaleFactors

let DeleteDuplicatedBlockRef() =
    let db = HostApplicationServices.WorkingDatabase
    use tr = db.TransactionManager.StartTransaction()
   
    let getRefs (bt: BlockTable) =
        let mutable lst = []
        for id in bt do
            let btr = tr.GetObject(id, OpenMode.ForRead) :?> BlockTableRecord
            for oId in btr.GetBlockReferenceIds(true, false) do
                lst <- tr.GetObject(oId, OpenMode.ForWrite) :?> BlockReference :: lst
        lst

    let rec findDups acc blks =
        match blks with
        | [] -> acc
        | h :: t -> let pair = List.partition (fun x -> Duplicate x h) t
                    findDups (acc @ (fst pair)) (snd pair)
    let delBlk lst =
        List.iter (fun (x: BlockReference) -> x.Erase()) lst
        lst.Length
               
    let cnt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
              |> getRefs |> findDups [] |> delBlk
    tr.Commit()
    cnt
       
[<CommandMethod("Test")>]
let Test() =
    try
        let del = DeleteDuplicatedBlockRef()
        Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased")
    with
        |ex -> Application.ShowAlertDialog(ex.Message)

69
Blocks / Re: Erase doubled block references
« on: November 23, 2010, 12:00:19 PM »
Hi,

By my side, I'd rather use a 'Duplicate' extension method for the BlockReference class than create a strucure.

Here's an example, in a 'BlockRefExtension' static class, two extension methods are defined to be used in the DeletDuplicatedBlockRef() method (a Test command is provided to test the code).
The GetName() method is needed while targeting the 2007 SDK (and perhaps 2088 and 2009) which doesn't contains the BlockReference.Name property.

EDIT: the DeletDuplicatedBlockRef() method returns the number of erased blocks
EDIT: removed some unusefull statements

Code: [Select]
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace DuplicateTest
{
    public static class BlockRefExtension
    {
        public static bool Duplicate(this BlockReference blk1, BlockReference blk2)
        {
            Tolerance tol = new Tolerance(1e-6, 1e-6);
            return
                blk1.GetName() == blk2.GetName() &&
                blk1.Layer == blk2.Layer &&
                Math.Round(blk1.Rotation, 5) == Math.Round(blk2.Rotation, 5) &&
                blk1.Position.IsEqualTo(blk2.Position, tol) &&
                blk1.ScaleFactors.IsEqualTo(blk2.ScaleFactors, tol);
        }

        public static string GetName(this BlockReference br)
        {
            using (Transaction tr = br.Database.TransactionManager.StartTransaction())
            {
                BlockTableRecord btr =
                    (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead);
                return btr.Name;
            }
        }
    }
    public class Commands
    {
        [CommandMethod("Test")]
        public void DelDupBlkRef()
        {
            try
            {
                int del = DeleteDuplicatedBlockRef();
                Application.ShowAlertDialog(del.ToString() + " duplicated block(s) have been erased");
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog("\nError: " + e.Message);
            }
        }

        private int DeleteDuplicatedBlockRef()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            int result = 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                foreach (ObjectId id in bt)
                {
                    BlockTableRecord btr =
                        (BlockTableRecord)tr.GetObject(id, OpenMode.ForWrite);
                    ObjectIdCollection idCol = btr.GetBlockReferenceIds(true, false);
                    for (int i = 0; i < idCol.Count; i++)
                    {
                        BlockReference blkRef =
                            (BlockReference)tr.GetObject(idCol[i], OpenMode.ForRead);
                        for (int j = i + 1; j < idCol.Count; j++)
                        {
                            BlockReference br =
                                (BlockReference)tr.GetObject(idCol[j], OpenMode.ForRead);
                            if (br.OwnerId == blkRef.OwnerId && br.Duplicate(blkRef))
                            {
                                idCol.RemoveAt(j);
                                br.UpgradeOpen();
                                br.Erase();
                                j--;
                                result++;
                            }
                        }
                    }
                }
                tr.Commit();
            }
            return result;
        }
    }
}

70
Layouts and printing / Re: Create and copy Layouts?
« on: November 23, 2010, 08:59:26 AM »
Hi,

Here's a little example to ceate a new layout with a viewport (maximum size according to paper margins).

Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace LayoutAndViewportSample
{
    public class CreateVpCommand
    {
        [CommandMethod("Test")]
        public void Test()
        {
            Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
            Database db = HostApplicationServices.WorkingDatabase;
           
            try
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    DBDictionary layouts = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForWrite);

                    // Get a layout name from the user
                    PromptStringOptions pso = new PromptStringOptions("\nEnter the layout name: ");
                    pso.AllowSpaces = true;
                    string name;
                    do
                    {
                        PromptResult pr = ed.GetString(pso);
                        if (pr.Status != PromptStatus.OK)
                            return;
                        name = pr.StringResult;
                    }
                    while (layouts.Contains(name));

                    // Create and activate the new layout
                    ObjectId layoutId = LayoutManager.Current.CreateLayout(name);
                    LayoutManager.Current.CurrentLayout = name;

                    // Calculate the maximum viewport size
                    Layout lay = (Layout)tr.GetObject(layoutId, OpenMode.ForWrite);
                    Point2d
                        minPt = lay.PlotPaperMargins.MinPoint,
                        maxPt = lay.PlotPaperMargins.MaxPoint,
                        pSize = lay.PlotPaperSize;
                    double width, height;
                    if ((int)lay.PlotRotation % 2 == 0)
                    {
                        width = pSize.X - maxPt.X - minPt.X;
                        height = pSize.Y - maxPt.Y - minPt.Y;
                    }
                    else
                    {
                        width = pSize.Y - maxPt.Y - minPt.Y;
                        height = pSize.X - maxPt.X - minPt.X;
                    }

                    // add the viewport to the layout BlockTableRecord
                    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(lay.BlockTableRecordId, OpenMode.ForWrite);
                    Viewport vp = new Viewport();
                    vp.Width = width;
                    vp.Height = height;
                    vp.CenterPoint = new Point3d(width / 2.0, height / 2.0, 0.0);
                    btr.AppendEntity(vp);
                    tr.AddNewlyCreatedDBObject(vp, true);
                    tr.Commit();
                }
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nError: " + ex.Message);
            }
        }
    }
}

target audience:{beginner}

71
C# language / Re: Code conversion from C# to VB
« on: November 22, 2010, 09:22:11 AM »
Hi,

This one seems to be quite good (but none is perfect).

72
Windows forms / Osnap Palette
« on: November 21, 2010, 11:00:48 PM »
Hi,

The _osnap dialog box as a palette



The 'OsPalette' class where the OSPALETTE command (to show the palette) is defined.
Code: [Select]
    using System;
    using Autodesk.AutoCAD.Runtime;
    using Autodesk.AutoCAD.Windows;

    namespace OsnapPalette
    {
        public class OsPalette
        {
            static PaletteSet ps;
            internal static OsmodeControl osmCtrl;

            public OsPalette()
            {
                osmCtrl = new OsmodeControl();
            }

            public void Show()
            {
                if (ps == null)
                {
                    ps = new PaletteSet("OSPALETTE", new Guid("{379AD059-A26C-4a3b-A05C-313A799D48CA}"));
                    ps.Style =
                      PaletteSetStyles.ShowPropertiesMenu |
                      PaletteSetStyles.ShowAutoHideButton |
                      PaletteSetStyles.ShowCloseButton;
                    ps.Name = "Accrochages aux objets";
                    ps.MinimumSize = new System.Drawing.Size(300, 340);
                    ps.Add("Accrobj", osmCtrl);
                }
                ps.Visible = true;
            }

            [CommandMethod("OSPALETTE")]
            public void Accobj()
            {
                this.Show();
            }
        }
    }

The 'OsmodeControl' class
Code: [Select]
    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using Autodesk.AutoCAD.ApplicationServices;
    using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
    using AcAs = Autodesk.AutoCAD.ApplicationServices;

    namespace OsnapPalette
    {
        public partial class OsmodeControl : UserControl
        {
            private Dictionary<int, CheckBox> modes = new Dictionary<int, CheckBox>();

            public OsmodeControl()
            {
                InitializeComponent();
                modes.Add(1, this.chkEnd);
                modes.Add(2, this.chkMid);
                modes.Add(4, this.chkCen);
                modes.Add(8, this.chkNod);
                modes.Add(16, this.chkQua);
                modes.Add(32, this.chkInt);
                modes.Add(64, this.chkIns);
                modes.Add(128, this.chkPer);
                modes.Add(256, this.chkTan);
                modes.Add(512, this.chkNea);
                modes.Add(2048, this.chkPrj);
                modes.Add(4096, this.chkExt);
                modes.Add(8192, this.chkPar);
                InitCheckBoxes();
                AcAp.SystemVariableChanged +=
                    new AcAs.SystemVariableChangedEventHandler(AcAp_SysvarChanged);
            }

            void AcAp_SysvarChanged(object sender, AcAs.SystemVariableChangedEventArgs e)
            {
                if (e.Name == "OSMODE" || e.Name == "AUTOSNAP")
                    InitCheckBoxes();
            }

            private void InitCheckBoxes()
            {
                short osmode = (short)AcAp.GetSystemVariable("OSMODE");
                foreach (KeyValuePair<int, CheckBox> pair in modes)
                {
                    pair.Value.Checked = (osmode & pair.Key) == pair.Key;
                }
                this.chkF3.Checked = (osmode & 16384) == 0;
                this.chkF11.Checked = (((short)AcAp.GetSystemVariable("AUTOSNAP")) & 16) == 16;
            }

            private void cmdAll_Click(object sender, EventArgs e)
            {
                foreach (KeyValuePair<int,CheckBox> pair in modes)
                {
                    pair.Value.Checked = true;
                }
            }

            private void cmdNone_Click(object sender, EventArgs e)
            {
                foreach (KeyValuePair<int, CheckBox> pair in modes)
                {
                    pair.Value.Checked = false;
                }
            }

            private void OsmodeControl_MouseLeave(object sender, EventArgs e)
            {
                Document doc = AcAp.DocumentManager.MdiActiveDocument;
                int autosnap = (short)AcAp.GetSystemVariable("AUTOSNAP");
                autosnap = chkF11.Checked ? autosnap | 16 : autosnap - (autosnap & 16);
                int osmode = 0;
                foreach (KeyValuePair<int,CheckBox> pair in modes)
                {
                    if (pair.Value.Checked)
                        osmode += pair.Key;
                }
                if (!chkF3.Checked)
                    osmode += 16384;
                using (DocumentLock docLock = doc.LockDocument())
                {
                    AcAp.SetSystemVariable("OSMODE", osmode);
                    AcAp.SetSystemVariable("AUTOSNAP", autosnap);
                }
            }
        }
    }

target audience:{intermediate}

73
Polylines / Add vertex
« on: November 21, 2010, 10:43:47 PM »
Hi,

The AVX command allows to add vertices to a polyline.
The `Jig' allows a dynamic preview of the new segment(s).
The command works whatever the polyline construction plane (`dynamic UCS' behavior while the polyline plane is different from the current UCS).
A DVX command allows to remove vertices

It deals with osnaps...


It deals with non constant widthes...


It deals with arc segments and with start and end points.


Code: [Select]
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace PolylineEdit
{
    public class AddVertex
    {
        Editor ed = acadApp.DocumentManager.MdiActiveDocument.Editor;
        Database db = HostApplicationServices.WorkingDatabase;

        class VertexJig : EntityJig
        {
            Polyline m_pline;
            Point3d m_point;
            int m_index;
            Vector3d m_vector;
            double m_bulge;
            double m_sWidth;
            double m_eWidth;

            public VertexJig(Polyline pline, Point3d point, int index, Vector3d vector, double bulge, double sWidth, double eWidth)
                : base(pline)
            {
                m_pline = pline;
                m_point = point;
                m_index = index;
                m_vector = vector;
                m_bulge = bulge;
                m_sWidth = sWidth;
                m_eWidth = eWidth;
            }

            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                JigPromptPointOptions jppo = new JigPromptPointOptions("\nSpecify the new vertex: ");
                jppo.UserInputControls = (UserInputControls.Accept3dCoordinates);
                PromptPointResult ppr = prompts.AcquirePoint(jppo);
                if (ppr.Status == PromptStatus.OK)
                {
                    if (ppr.Value.IsEqualTo(m_point))
                        return SamplerStatus.NoChange;
                    else
                    {
                        m_point = ppr.Value;
                        return SamplerStatus.OK;
                    }
                }
                return SamplerStatus.Cancel;
            }

            protected override bool Update()
            {
                if (m_pline.NumberOfVertices == 3)
                {
                    Point3d transPt = m_point.TransformBy(Matrix3d.WorldToPlane(m_pline.Normal));
                    Point2d pt = new Point2d(transPt.X, transPt.Y);
                    double length = m_pline.GetDistanceAtParameter(2);
                    double dist1 = m_pline.GetDistanceAtParameter(1);
                    double dist2 = length - dist1;
                    double width = m_sWidth < m_eWidth ?
                        ((dist1 * (m_eWidth - m_sWidth)) / length) + m_sWidth :
                        ((dist2 * (m_sWidth - m_eWidth)) / length) + m_eWidth;
                    double angle = Math.Atan(m_bulge);
                    m_pline.SetPointAt(m_index, pt);
                    m_pline.SetEndWidthAt(0, width);
                    m_pline.SetStartWidthAt(1, width);
                    m_pline.SetBulgeAt(0, Math.Tan(angle * (dist1 / length)));
                    m_pline.SetBulgeAt(1, Math.Tan(angle * (dist2 / length)));
                }
                else if (m_index == 0)
                {
                    Point3d transPt = m_point.TransformBy(Matrix3d.WorldToPlane(m_pline.Normal));
                    Point2d pt = new Point2d(transPt.X, transPt.Y);
                    m_pline.SetPointAt(m_index, pt);
                    if (m_bulge != 0.0)
                    {
                        Vector3d vec = m_point.GetVectorTo(m_pline.GetPoint3dAt(1));
                        double ang = vec.GetAngleTo(m_vector, m_pline.Normal);
                        double bulge = Math.Tan(ang / 2.0);
                        m_pline.SetBulgeAt(0, bulge);
                    }
                }
                else
                {
                    Point3d transPt = m_point.TransformBy(Matrix3d.WorldToPlane(m_pline.Normal));
                    Point2d pt = new Point2d(transPt.X, transPt.Y);
                    m_pline.SetPointAt(m_index, pt);
                    if (m_bulge != 0.0)
                    {
                        Vector3d vec = m_pline.GetPoint3dAt(0).GetVectorTo(m_point);
                        double ang = m_vector.GetAngleTo(vec, m_pline.Normal);
                        double bulge = Math.Tan(ang / 2.0);
                        m_pline.SetBulgeAt(0, bulge);
                    }
                }
                return true;
            }

            public Point3d GetPoint()
            {
                return m_point;
            }
        }

        [CommandMethod("AVX")]
        public void Avx()
        {
            PromptEntityOptions peo = new PromptEntityOptions("\nSelect a segment where to add a vertex: ");
            peo.SetRejectMessage("\nIncorrect entity");
            peo.AllowNone = false;
            peo.AllowObjectOnLockedLayer = false;
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status == PromptStatus.OK)
            {
                Matrix3d UCS = ed.CurrentUserCoordinateSystem;
                ObjectId objId = per.ObjectId;
                try
                {
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        Polyline pline = tr.GetObject(objId, OpenMode.ForRead, false) as Polyline;
                        if (pline != null)
                        {
                            Point3d pickPt = pickPointOnPline(pline, per.PickedPoint);
                            double param = pline.GetParameterAtPoint(pickPt);
                            int index = (int)param;

                            Matrix3d OCS = Matrix3d.PlaneToWorld(pline.Normal);
                            Point3d transPt = pickPt.TransformBy(OCS);

                            if (!OCS.CoordinateSystem3d.Zaxis.IsEqualTo(UCS.CoordinateSystem3d.Zaxis))
                            {
                                ed.CurrentUserCoordinateSystem = plineUCS(pline, index);
                            }

                            Int16 aperture = (Int16)acadApp.GetSystemVariable("APERTURE");
                            double viewsize = (double)acadApp.GetSystemVariable("VIEWSIZE");
                            Point2d screensize = (Point2d)acadApp.GetSystemVariable("SCREENSIZE");
                            double tol = 2 * aperture * viewsize / screensize.Y;
                            Tolerance tolerance = new Tolerance(tol, tol);

                            int endParam = pline.Closed == true ? pline.NumberOfVertices : pline.NumberOfVertices - 1;
                            Vector3d vec;

                            using (Polyline ghost = new Polyline())
                            {
                                ghost.ColorIndex = 7;

                                if ((pline.Closed == false) && pickPt.IsEqualTo(pline.GetPoint3dAt(0), tolerance))
                                {
                                    vec = pline.GetFirstDerivative(0);
                                    double bulge = pline.GetBulgeAt(0);
                                    double width = pline.GetStartWidthAt(0);
                                    Point2d p0 = new Point2d(transPt.X, transPt.Y);
                                    Point2d p1 = pline.GetPoint2dAt(0);

                                    ghost.AddVertexAt(0, p0, bulge, width, width);
                                    ghost.AddVertexAt(1, p1, bulge, width, width);
                                    ghost.Normal = pline.Normal;
                                    ghost.Elevation = pline.Elevation;

                                    VertexJig jig = new VertexJig(ghost, pickPt, 0, vec, bulge, width, width);

                                    PromptResult res = ed.Drag(jig);
                                    if (res.Status == PromptStatus.OK)
                                    {
                                        pline.UpgradeOpen();
                                        pline.AddVertexAt(index, ghost.GetPoint2dAt(0), ghost.GetBulgeAt(0), width, width);
                                    }
                                }
                                else if ((pline.Closed == false) && pickPt.IsEqualTo(pline.GetPoint3dAt(endParam), tolerance))
                                {
                                    vec = pline.GetFirstDerivative(endParam);
                                    double bulge = pline.GetBulgeAt(index);
                                    double width = pline.GetEndWidthAt(endParam);
                                    Point2d p0 = pline.GetPoint2dAt(endParam);
                                    Point2d p1 = new Point2d(transPt.X, transPt.Y);

                                    ghost.AddVertexAt(0, p0, bulge, width, width);
                                    ghost.AddVertexAt(1, p1, bulge, width, width);
                                    ghost.Normal = pline.Normal;
                                    ghost.Elevation = pline.Elevation;

                                    VertexJig jig = new VertexJig(ghost, pickPt, 1, vec, bulge, width, width);

                                    PromptResult res = ed.Drag(jig);
                                    if (res.Status == PromptStatus.OK)
                                    {
                                        pline.UpgradeOpen();
                                        pline.AddVertexAt(endParam + 1, ghost.GetPoint2dAt(1), ghost.GetBulgeAt(0), width, width);
                                        pline.SetBulgeAt(endParam, ghost.GetBulgeAt(0));
                                    }
                                }

                                else
                                {
                                    double bulge = pline.GetBulgeAt(index);
                                    double sWidth = pline.GetStartWidthAt(index);
                                    double eWidth = pline.GetEndWidthAt(index);
                                    Point2d p0 = pline.GetPoint2dAt(index);
                                    Point2d p1 = new Point2d(transPt.X, transPt.Y);
                                    Point2d p2;
                                    if (pline.Closed == false)
                                        p2 = pline.GetPoint2dAt(index + 1);
                                    else
                                    {
                                        try { p2 = pline.GetPoint2dAt(index + 1); }
                                        catch { p2 = pline.GetPoint2dAt(0); }
                                    }

                                    ghost.AddVertexAt(0, p0, bulge, sWidth, 0.0);
                                    ghost.AddVertexAt(1, p1, bulge, 0.0, eWidth);
                                    ghost.AddVertexAt(2, p2, 0.0, 0.0, 0.0);
                                    ghost.Normal = pline.Normal;
                                    ghost.Elevation = pline.Elevation;

                                    VertexJig jig = new VertexJig(ghost, pickPt, 1, vec, bulge, sWidth, eWidth);

                                    PromptResult res = ed.Drag(jig);
                                    if (res.Status == PromptStatus.OK)
                                    {
                                        pline.UpgradeOpen();
                                        pline.SetEndWidthAt(index, ghost.GetStartWidthAt(1));
                                        pline.AddVertexAt(index + 1, ghost.GetPoint2dAt(1), ghost.GetBulgeAt(1), ghost.GetStartWidthAt(1), eWidth);
                                        pline.SetBulgeAt(index, ghost.GetBulgeAt(0));
                                    }
                                }
                            }
                            ed.CurrentUserCoordinateSystem = UCS;
                        }
                        tr.Commit();
                    }
                }
                catch (System.Exception ex)
                {
                    ed.CurrentUserCoordinateSystem = UCS;
                    ed.WriteMessage("Error: " + ex.Message);
                }
            }
        }

        [CommandMethod("DVX")]
        public void Dvx()
        {
            PromptEntityOptions peo = new PromptEntityOptions("\nSelact the vertex to remove: ");
            peo.SetRejectMessage("\nIncorrect entity");
            peo.AllowNone = false;
            peo.AllowObjectOnLockedLayer = false;
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status == PromptStatus.OK)
            {
                ObjectId objId = per.ObjectId;
                try
                {
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        Polyline pline = tr.GetObject(objId, OpenMode.ForWrite, false) as Polyline;
                        if (pline != null)
                        {
                            if (pline.NumberOfVertices > 2)
                            {
                                Point3d pickPt = pickPointOnPline(pline, per.PickedPoint);
                                double param = pline.GetParameterAtPoint(pickPt);
                                int index = (int)param;
                                if ((param - Math.Truncate(param)) > 0.5)
                                    index += 1;
                                pline.RemoveVertexAt(index);
                            }
                            else
                                ed.WriteMessage("\nOnly two vertices left");
                        }
                        tr.Commit();
                    }
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("Error: " + ex.Message);
                }
            }
        }

        private Point3d pickPointOnPline(Polyline pl, Point3d pt)
        {
            pt = pt.TransformBy(ed.CurrentUserCoordinateSystem);
            Vector3d vdir = ed.GetCurrentView().ViewDirection;
            pt = pt.Project(pl.GetPlane(), vdir);
            return pl.GetClosestPointTo(pt, false);
        }

        private Matrix3d plineUCS(Polyline pline, int param)
        {
            Point3d origin = pline.GetPoint3dAt(param);
            Vector3d xDir = origin.GetVectorTo(pline.GetPoint3dAt(param + 1)).GetNormal();
            Vector3d zDir = pline.Normal;
            Vector3d yDir = zDir.CrossProduct(xDir).GetNormal();
            return new Matrix3d(new double[16]{
                xDir.X, yDir.X, zDir.X, origin.X,
                xDir.Y, yDir.Y, zDir.Y, origin.Y,
                xDir.Z, yDir.Z, zDir.Z, origin.Z,
                0, 0, 0, 1});
        }
    }
}

target audience:{advanced}

74
Text / Strip Mtext
« on: November 21, 2010, 09:57:29 PM »
Hi,

This code was inspired by a Tony Tanzillo's one using the Mtext.ExplodeFragments() method to remove all Mtext formatting.

A command: STRIPMT to unformat all selected Mtexts
A LISP function: gc-GetStrippedMtextString to return the unformated text string of the mtext which ename is passed as argument to the function

Code: [Select]
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace StripMtextSample
{
    public class StripMtext
    {
        private StringBuilder m_sb = null;

        private string GetStrippedMtextContents(MText mt)
        {
            m_sb = new StringBuilder();
            mt.ExplodeFragments(new MTextFragmentCallback(FragmentCallback));
            return m_sb.ToString();
        }

        private MTextFragmentCallbackStatus FragmentCallback(MTextFragment fragment, object obj)
        {
            m_sb.Append(fragment.Text);
            return MTextFragmentCallbackStatus.Continue;
        }

        [CommandMethod("STRIPMT", CommandFlags.Modal | CommandFlags.UsePickSet)]
        public void StripSelSet()
        {
            Document doc = AcAp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            SelectionFilter filter = new SelectionFilter(new TypedValue[] { new TypedValue(0, "MTEXT") });
            ed.WriteMessage("\nSelect mtexts (or type 'Enter' for 'all').");
            PromptSelectionResult psr = ed.GetSelection(filter);
            if (psr.Status == PromptStatus.Error)
                psr = ed.SelectAll(filter);
            if (psr.Status != PromptStatus.OK)
                return;
            try
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    foreach (ObjectId id in psr.Value.GetObjectIds())
                    {
                        MText mt = (MText)tr.GetObject(id, OpenMode.ForWrite);
                        mt.Contents = GetStrippedMtextContents(mt);
                    }
                    tr.Commit();
                }
            }
            catch (System.Exception e)
            {
                ed.WriteMessage(string.Format("\nError: {0}\n", e.Message));
            }
        }

        [LispFunction("gc-GetStrippedMtextString")]
        public string GetStrippedMtextString(ResultBuffer resbuf)
        {
            try
            {
                if (resbuf == null)
                    throw new LispException("to few arguments");
                TypedValue[] arg = resbuf.AsArray();
                if (arg.Length > 1)
                    throw new LispException("to many arguments");
                if (arg[0].TypeCode != (short)LispDataType.ObjectId)
                    throw new LispException(string.Format("incorrect argument type: lentityp: {0}", arg[0].Value));
                Database db = HostApplicationServices.WorkingDatabase;
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    MText mt = tr.GetObject(((ObjectId)arg[0].Value), OpenMode.ForRead) as MText;
                    if (mt == null)
                        throw new LispException("incorrect argument type: not a mtext");
                    return GetStrippedMtextContents(mt);
                }
            }
            catch (LispException e)
            {
                AcAp.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nError: {0}\n", e.Message);
                return null;
            }
        }
    }

    class LispException : System.Exception
    {
        public LispException(string message)
            : base(message)
        {
        }
    }
}

target audience:{intermediate}

75
Layouts and printing / Re: Check Paper/Model Space
« on: November 19, 2010, 07:08:18 PM »
Talking about short code, I forgot to post a F# example
Code: [Select]
let F_TestPaperSpace() =
    LayoutManager.Current.CurrentLayout <> "Model"

Pages: 1 ... 3 4 [5] 6