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 - frits432

Pages: [1]
1
Layouts and printing / Re: Find out which paper size to use
« on: December 24, 2013, 02:47:55 PM »
layout.Extents;

2
Layouts and printing / Re: zoom and rotate viewport
« on: December 24, 2013, 02:45:06 PM »
Still need help with Viewport View settings?

3
Blocks / Re: how can i redefine a block
« on: April 12, 2012, 03:57:32 PM »
What kind of changed do you want to make ?
On of the simplest change to a block is appending an entity to the ModelSpace Block, like so:

Code: [Select]
[CommandMethod("drawline")]
    static public void drawline()
    {
      Database db = HostApplicationServices.WorkingDatabase;
      using (Transaction tr = db.TransactionManager.StartTransaction())
     
        BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
        BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
        Line ln = new Line(new Point3d(10, 10, 0), new Point3d(20, 20, 0));
        ms.AppendEntity(ln);
        tr.AddNewlyCreatedDBObject(ln, true);
        tr.Commit();
      }
    }

4
Layouts and printing / Re: Move Layout to other position
« on: February 09, 2012, 09:42:42 AM »
You might have  forgotten to "Open" the layouts.
The code below is ordering the layout's based on their names.
based on an article of
Norman Yuan http://drive-cad-with-code.blogspot.com/2011/06/set-layout-in-order.html

See attachments 1 and 2 for an example of the layout names

Quote
   public class MyCommands
    {
        [CommandMethod("OrderLayout")]
        public static void OrderAllLayouts()
        {
            Document dwg = Application.DocumentManager.MdiActiveDocument;
            Editor ed = dwg.Editor;

            SetLayoutOrder();
            ed.Regen();
        }

        private static void SetLayoutOrder()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            var layouts = new Dictionary<string, Layout>();

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                DBDictionary layoutDICT = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                ed.WriteMessage("\nBefore Sort");
                long j = 0;
                foreach (DBDictionaryEntry dictEntry in layoutDICT)
                {
                    Layout layout = tr.GetObject(dictEntry.Value, OpenMode.ForRead) as Layout;
                    if (!layout.ModelType)
                    {
                        layouts.Add(layout.LayoutName, layout);
                        ed.WriteMessage("\n Layout[{0}]={1}, tab={2}", j++, layout.LayoutName, layout.TabOrder);
                    }
                }
                var sortedLayoutNames = layouts.Keys
                 .Where(n => n.Contains('-'))
                 .Select(n => n.Split(new char[] { '-' }))
                 .OrderBy(n => n[0])
                 .ThenBy(n => n[1])
                 .ThenBy(n => Convert.ToInt32(n[2]))
                 .Select(n => string.Join("-", n))
                .Select((n, i) => { layouts[n].UpgradeOpen(); layouts[n].TabOrder = i + 1; return i + layouts[n].LayoutName; }).ToList();

                //ed.WriteMessage("\nsortedLayoutNames");
                //foreach (string sortedLayoutname in sortedLayoutNames)
                //    ed.WriteMessage("\n{0}", sortedLayoutname);

                ed.WriteMessage("\nAfter Sort");
                j = 0;
                foreach (DBDictionaryEntry dictEntry in layoutDICT)
                {
                    Layout layout = tr.GetObject(dictEntry.Value, OpenMode.ForRead) as Layout;
                    ed.WriteMessage("\n Layout[{0}]={1}, tab={2}", j++, layout.LayoutName, layout.TabOrder);
                }

                tr.Commit();

            }
        }
}

5
Layouts and printing / Re: Export each Layout and Modelspace to new Drawing
« on: February 03, 2012, 05:12:09 PM »
Doesn't contribute to any award and not the best way to do it, but it might get you get started

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

using System.Collections.Generic;
using System.Linq;
using System.IO;


// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(AcadExport.MyCommands))]

namespace AcadExport
{
    public class MyCommands
    {
        [CommandMethod("ExportLayout", CommandFlags.Modal | CommandFlags.Session)]
        public void ExportLayout() // This method can have any name
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            //if (doc.Name.Length < 1)
            //{
            //    ed.WriteMessage("\nDrawing not saved yet");
            //    return;
            //}
            //string docPath = Path.GetDirectoryName(doc.Name);
            //string docFilename = Path.GetFileNameWithoutExtension(doc.Name);

            foreach (string lytName in GetLayoutNames(db))
            {
                CopyLayout(doc.Name, lytName);
            }
            Application.DocumentManager.MdiActiveDocument=doc;

        }

 


        public List<string> GetLayoutNames(Database db)
        {
            var layoutNames = new List<string>();

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                DBDictionary lytDct = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                foreach (DBDictionaryEntry lytDe in lytDct)
                {
                    if (lytDe.Key != "Model")
                    {
                        //Return the names of Non Empty Layouts only
                        Layout lyt = (Layout)tr.GetObject(lytDe.Value, OpenMode.ForRead);
                        BlockTableRecord ltr = (BlockTableRecord)tr.GetObject(lyt.BlockTableRecordId, OpenMode.ForRead);
                        if (ltr.Cast<ObjectId>().Count() > 1)
                            layoutNames.Add(lyt.LayoutName);
                    }
                }
                tr.Commit();
            }
            return layoutNames;
        }


        public void CopyLayout(string docPathname, string layoutName)
        {
            string tmpPathname = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".dwg");
            string expDocPathname = Path.Combine(
            Path.GetDirectoryName(docPathname),
            Path.GetFileNameWithoutExtension(docPathname) +
            "_" + layoutName + ".dwg");

            File.Copy(docPathname, tmpPathname, true);

            Document doc = Application.DocumentManager.Open(tmpPathname, false);
            Application.DocumentManager.MdiActiveDocument = doc;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (doc.LockDocument())
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    LayoutManager.Current.CurrentLayout = layoutName;
                    DBDictionary lytDct = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                    foreach (DBDictionaryEntry dictEntry in lytDct)
                    {
                        if (dictEntry.Key != "Model" && dictEntry.Key != layoutName)
                        {
                            Layout lyt = (Layout)tr.GetObject(dictEntry.Value, OpenMode.ForWrite);
                            //if (!lyt.ModelType)
                            lyt.Erase();
                        }
                    }
                    tr.Commit();
                    ed.Regen();
                }

                db.SaveAs(expDocPathname,true, DwgVersion.Newest,db.SecurityParameters);
            }
            //File.Delete(tmpPathname);
        }

    }
}


6
Events / Re: Query for EventHandlers
« on: November 21, 2011, 10:37:18 PM »

Quote
So it' possible to systematically remove the handler before adding it.
But this may take a while if you need to guess how often you have to remove handlers.  :reprobateur:
I'll stick to the
Code: [Select]
if (!eventsEnabled)Thanks Gile.

7
Events / Re: Query for EventHandlers
« on: November 21, 2011, 09:20:27 AM »
Hi Gile,
Thanks you for replying and sorry for my late responding.
While experimenting i noticed that i can remove the eventhandler without errors even if it is not defined.
So for the code below I can always call REMEV as much as i like without calling ADDEV.
The line "\nFailed to remove eventhandler" will never be executed
So i think the only solution is to add a variable eventsEnabled to prevent duplicated calls to ADDEV

Gr,
Frits

However everytime you call ADDEV, new (duplicated) eventhandlers will be added.
So

Code: [Select]
        [CommandMethod("AddEv")]
        public void AddEvents()
        {
            LayoutManager layMgr = LayoutManager.Current;
            layMgr.LayoutSwitched += new Autodesk.AutoCAD.DatabaseServices.LayoutEventHandler(OnLayoutSwitched);

        }

        [CommandMethod("RemEv")]
        public void RemoveEvents()
        {
            try
            {
                LayoutManager layMgr = LayoutManager.Current;
                layMgr.LayoutSwitched -= new Autodesk.AutoCAD.DatabaseServices.LayoutEventHandler(OnLayoutSwitched);
            }
            catch
            {
                Document doc = Application.DocumentManager.MdiActiveDocument;
                Editor ed = doc.Editor;
                ed.WriteMessage("\nFailed to remove eventhandler");
            }

        }

       public void OnLayoutSwitched(object senderObj, Autodesk.AutoCAD.DatabaseServices.LayoutEventArgs layoutEventArgs)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            ed.WriteMessage("\nOnLayoutSwitched={0}", layoutEventArgs.Name);
        }

8
Events / Query for EventHandlers
« on: November 16, 2011, 09:29:53 AM »
While experimenting with events i noticed that you can add the same handler more than once but found no easy way to prevent this, other than define static variables remembering events already enabled.
Such as
Code: [Select]
public static class Class1
    {
        private bool eventsEnabled;
         public void EnableEvents()
         {
             if (!eventsEnabled)
             {
                 LayoutManager.Current.LayoutSwitched += new Autodesk.AutoCAD.DatabaseServices.LayoutEventHandler(OnLayoutSwitched);
                 eventsEnabled = true;
...

Is it possible to Query for already enabled Events, like

if (!LayoutManager.Current.LayoutSwitched.Has(OnLayoutSwitched))
LayoutManager.Current.LayoutSwitched += ...

Thanks for any help.



9
Selection sets / Re: Selection Set Filters
« on: November 16, 2011, 09:17:39 AM »
Amazing, this gives me even more options to write nicer code.
Thanks.

10
Math and Geometry / Re: Geometry extensions
« on: November 16, 2011, 09:14:36 AM »
Gile,
You're right, this "pvp2.DCS2WCS() * pvp2.PSDCS2DCS()" was the transformation what i am looking for.
Thanks Gile, you're the expert!

11
Selection sets / Re: Selection Set Filters
« on: November 15, 2011, 12:28:24 PM »
In combination with the Kaefer extensions for DBObjects  they can be made even easier

Code: [Select]

  public static class KaeferExtensions
    {
        // Opens a DBObject in ForRead mode (kaefer @ TheSwamp)
        public static T GetObject<T>(this ObjectId id) where T : DBObject
        {
            return id.GetObject<T>(OpenMode.ForRead);
        }

        // Opens a DBObject in the given mode (kaefer @ TheSwamp)
        public static T GetObject<T>(this ObjectId id, OpenMode mode) where T : DBObject
        {
            return id.GetObject(mode) as T;
        }
        // Opens a collection of DBObject in ForRead mode (kaefer @ TheSwamp)       
        public static IEnumerable<T> GetObjects<T>(this IEnumerable ids) where T : DBObject
        {
            return ids.GetObjects<T>(OpenMode.ForRead);
        }

        // Opens a collection of DBObject in the given mode (kaefer @ TheSwamp)
        public static IEnumerable<T> GetObjects<T>(this IEnumerable ids, OpenMode mode) where T : DBObject
        {
            return ids
                .Cast<ObjectId>()
                .Select(id => id.GetObject<T>(mode))
                .Where(res => res != null);
        }

        // Applies the given Action to each element of the collection (mimics the F# Seq.iter function).
        public static void Iterate<T>(this IEnumerable<T> collection, Action<T> action)
        {
            foreach (T item in collection) action(item);
        }

        // Applies the given Action to each element of the collection (mimics the F# Seq.iteri function).
        // The integer passed to the Action indicates the index of element.
        public static void Iterate<T>(this IEnumerable<T> collection, Action<T, int> action)
        {
            int i = 0;
            foreach (T item in collection) action(item, i++);
        }
    }

...

//using KeaderExtensions:
                    pvpFrozenLayerNames = lt.GetObjects<LayerTableRecord>()
                        .Where(ly => ly.IsOff)
                        .Where(ly => ly.IsFrozen)
                        .Select(ly => ly.Name)
                        .ToList();






12
Selection sets / Re: Selection Set Filters
« on: November 15, 2011, 12:11:01 PM »
Gile,
Very useful code for complex selecting in large drawings.
However for smaller drawings and easier to maintain code i like the LINQ approach as well, because it enables me to use the same code pattern to use all type of selections.
Selection based on entity type, layer, string contents, location etc.

Some samples.

Code: [Select]
using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead);
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                BlockTableRecord ps = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.PaperSpace], OpenMode.ForWrite);
                    LayoutManager layMgr = LayoutManager.Current;
                    Layout lay = (Layout)tr.GetObject(layMgr.GetLayoutId(layMgr.CurrentLayout), OpenMode.ForRead);


//Collect LayerNames to exclude e.q.  Layers OFF or Frozen
List<string> frozenLayerNames= lt
                        .Cast<ObjectId>()
                        .Select(id => (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead))
                        .Where(ly => ly.IsOff)
                        .Where(ly => ly.IsFrozen)
                        .Select(ly => ly.Name)
                        .ToList();

//Same but now from within PaperSpace Viewports
List<string> pvpFrozenLayerNames = lay
                        .GetViewports().Cast<ObjectId>()
                        .Select(id => (Viewport)tr.GetObject(id, OpenMode.ForRead))
                        .SelectMany(pvp => pvp.GetFrozenLayers().Cast<ObjectId>())
                        .Distinct().ToArray()
                        .Select(id => (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead))
                        .Select(ly => ly.Name)
                        .ToList();

// List (visible) Layers named "...~..." and "...TXT..." and NOT "...NOTTOBEINCLUDED..."
var visLayerNames = lt
                    .Cast<ObjectId>()
                    .Select(id => (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead))
                    .Where(ly => ly.Name.Contains('~'))
                    .Where(ly => ly.Name.IndexOf("TXT", StringComparison.CurrentCultureIgnoreCase) > 0)
                    .Where(ly => ly.Name.IndexOf("NOTTOBEINCLUDED", StringComparison.CurrentCultureIgnoreCase) < 0)
                    .Where(ly => !ly.IsOff)
                    .Where(ly => !ly.IsFrozen)
                    .Where(ly => !pvpFrozenLayerNames.Contains(ly.Name))
                    .Select(ly => ly.Name)
                    .ToList();

//select ModelSpace Text from specific layers
               var visTxt = ms.Cast<ObjectId>()
                    .Where(id => id.ObjectClass.DxfName.ToUpper() == "TEXT" || id.ObjectClass.DxfName.ToUpper() == "MTEXT")
                    .Select(id => (Entity)tr.GetObject(id, OpenMode.ForRead))
                    .Where(ent => visLayerNames.Contains(ent.Layer))
                    .ToList();

//select Text from specific layers within specific Blocks
               var visTxtInSpecificBlks = ms.Cast<ObjectId>()
                    .Where(id => id.ObjectClass.DxfName.ToUpper() == "INSERT")
                    .Select(id => (BlockReference)tr.GetObject(id, OpenMode.ForRead))
                    .Where(blkRef => visLayerNames.Contains(blkRef.Layer))
                    .Where(blkRef => blkRef.Name.IndexOf("-xxx-", StringComparison.CurrentCultureIgnoreCase) > 0)
                    .SelectMany(blkRef => ((BlockTableRecord)tr.GetObject(bt[blkRef.Name], OpenMode.ForRead)).Cast<ObjectId>())
                    .Where(id => id.ObjectClass.DxfName.ToUpper() == "TEXT" || id.ObjectClass.DxfName.ToUpper() == "MTEXT")
                    .Select(id => (Entity)tr.GetObject(id, OpenMode.ForRead))
                    .Where(ent => visLayerNames.Contains(ent.Layer))
                    .ToList();

//Join Modelspace and Block Specific text
                visTxt.AddRange(visTxtInSpecificBlks);


// build regular pattern to select certain string contents
// use regex tester to help build the search pattern.
                string searchNrs = @"(^3\(|^)(...)(.*)";
                string returnNrs = "$2";
                var matchNr = new Regex(searchNrs , RegexOptions.IgnoreCase | RegexOptions.Compiled);


//find visible text containing a complex patter
                var textNrs = visTxt
                    .Select(ent => GetType().Name == "MTEXT" ? ((MText)ent).Text : ((DBText)ent).TextString)
                    .Select(txt => matchNr.Replace(txt, searchNrs))
                    .Distinct().ToArray()
                    .ToList();

//List in numeric order
                kabelNrs = kabelNrs
                    .OrderBy(kabelNr => kabelNr.Length)
                    .ThenBy(kabelNr => kabelNr)
                    .ToList();
...





13
Math and Geometry / Re: Geometry extensions
« on: November 15, 2011, 10:13:09 AM »
Hi Gile,
Thank you for posting this new version. Currently i am working on the Paperspace to Modelspace transformation and testing code for these calculations. But i can't get it right.
This is the scenario:
Simple Viewport rotated and zoomed to a rectangle in modelspace, see attachment.
When executing the command MSPVP1 an exact matching rectangle presenting the Paperspace Viewport border will be created in Modelspace.
When executing the command msPVPByGile there is a small displacement.
I suppose there is a problem with the order of the Matrix transformation in
Matrix3d ps2wcs = pvp2.PSDCS2DCS() * pvp2.DCS2WCS();

Any suggestions?
Greetings,
Frits




14
Math and Geometry / Re: Geometry extensions
« on: November 03, 2011, 09:18:45 AM »
Hi Gile,
Thanks for the response.
This is the region implementation and it works well for relatively simple profiles like profile2.

...
                var plines = new List<Polyline>();
                foreach (PolylineSegmentCollection segs in psc.Join())
                {
                    Polyline pline = segs.ToPolyline();
                    plines.Add(pline);
                }
                ed.WriteMessage("\n{0} boundaries", plines.Count);
                plines.OrderByDescending(p => p.Area);
                Polyline plineContour = plines.First();
                    DBObjectCollection outerCurves = new DBObjectCollection { plineContour };
                    DBObjectCollection outerRegion = Region.CreateFromCurves(outerCurves);
                    Solid3d solidPart = new Solid3d();
                    solidPart.Extrude((Region)outerRegion[0], 1.0, 0.0);
                plines.Remove(plineContour);

               foreach (Polyline plineHoles in plines)
                {
                    DBObjectCollection holeCurves = new DBObjectCollection { plineHoles };
                    DBObjectCollection holeRegions = Region.CreateFromCurves(holeCurves);
                    Solid3d solidHole = new Solid3d();
                    solidHole.Extrude((Region)holeRegions[0], 1.0, 0.0);
                    solidPart.BooleanOperation(BooleanOperationType.BoolSubtract, solidHole);
                }
                Point3d centroid = solidPart.MassProperties.Centroid;
                ed.WriteMessage("\nCentroid={0}", centroid);
                Vector3d moI = solidPart.MassProperties.MomentsOfIntertia;
                ed.WriteMessage("\nMomentsOfIntertia={0}", moI);
...

But for  the more advanced contours like profile3 the conversion to regions often fails. That's why i implemented that VBA solution a few years ago.

Currently i try  to implement any of the following solutions:
1. conversion of the VBA  program Circle Cone + trapezoid calculations;
2. circle segments + triangles calculations following you're code in PlineAlgebraicArea(...);
3. circle segments + "cross section defined as polygon" 
     from http://en.wikipedia.org/wiki/Second_moment_of_area

The second one is my favorite because of the simplicity(== elegance) of your code, however the implementation of the Inertia calculation for rotated non symmetrical triangles is a bit  tricky. It requires additional Ixy calculations.

Again thanks.
Frits


15
Math and Geometry / Geometry extensions/Moments of Inerita
« on: November 01, 2011, 04:06:50 PM »
Hi Gile,
If anyone can help you're the one.
I few years ago i wrote a VBA program for AutoCAD doing Geometric calculations on Boundaries -- Polylines including Polylines.
Part of the program involved the creation of the closed polylines, which you have elegantly solved in c#.
Another Part is the calculation of the Moments of Inertia and the the Centroids also solved in the Geometry Extensions class.
I've tried to include the Moments of Inertia calculation but because of too little experience in c# not succeeded yet.

The problem is that to my knowledge the Moments of Inertia can exactly be determined for (rotated) arc shaped contours using a Cone(Segment+Triangle), not a Segment. (see GeoCalcArc)

I like the way you calculate the area dividing everything in triangles and Arc Segment, it's far more elegant than my way of dividing everything in cones and trapezoid.

Have you any experience with the Inertia calculations, and if so can you help me out here.

Thanks,
Frits


Pages: [1]