TheSwamp
Code Red => .NET => Topic started by: It's Alive! on January 01, 2010, 11:22:25 AM
-
Just reading David's blog http://blog.davidkblackmon.com/
here is my easier way for C# :laugh:
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
namespace ExecMethod
{
public class SelectionFilterBuilder : List<TypedValue>
{
public SelectionFilterBuilder()
{
}
public SelectionFilterBuilder(DxfCode code, params string[] list)
{
base.Add(new TypedValue((short)code, FormatString(list)));
}
// Methods
public void AddDxfCode(DxfCode code, object val)
{
base.Add(new TypedValue((short)code, val));
}
public void AddEntityFilter(params string[] list)
{
base.Add(new TypedValue(0, FormatString(list)));
}
public void AddLayerFilter(params string[] list)
{
base.Add(new TypedValue(8, FormatString(list)));
}
internal static string FormatString(params string[] list)
{
StringBuilder sb = new StringBuilder();
foreach (string s in list)
{
sb.Append(s);
sb.Append(",");
}
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
public static implicit operator SelectionFilter(SelectionFilterBuilder src)
{
return new SelectionFilter(src.ToArray());
}
}
}
then
[CommandMethod("doit")]
static public void doit()
{
Editor acDocEd = Application.DocumentManager.MdiActiveDocument.Editor;
var builder = new SelectionFilterBuilder();
builder.AddEntityFilter("CIRCLE","LINE");
builder.AddLayerFilter("1","2");
var acSSPrompt = acDocEd.GetSelection(builder);
if (acSSPrompt.Status == PromptStatus.OK)
{
SelectionSet acSSet = acSSPrompt.Value;
Application.ShowAlertDialog(String.Format("{0}: ",acSSet.Count));
return;
}
Application.ShowAlertDialog("Number of objects selected: 0");
}
or
[CommandMethod("doit")]
static public void doit()
{
Editor acDocEd = Application.DocumentManager.MdiActiveDocument.Editor;
var builder = new SelectionFilterBuilder(DxfCode.Start, "CIRCLE","LINE");
var acSSPrompt = acDocEd.GetSelection(builder);
if (acSSPrompt.Status == PromptStatus.OK)
{
SelectionSet acSSet = acSSPrompt.Value;
Application.ShowAlertDialog(String.Format("{0}: ",acSSet.Count));
return;
}
Application.ShowAlertDialog("Number of objects selected: 0");
}
-
That's good
I have improved a bit, so that may be more concise writing
using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
namespace TlsCad.Collections
{
/// <summary>
/// TypedValue Collection
/// </summary>
public class ResultList : List<TypedValue>
{
public ResultList()
: base()
{ }
public ResultList(IEnumerable<TypedValue> collection)
: base(collection)
{ }
public void Add(int typeCode, object obj)
{
base.Add(new TypedValue(typeCode, obj));
}
public void Add(LispDataType type, object obj)
{
base.Add(new TypedValue((int)type, obj));
}
public void Add(DxfCode type, object obj)
{
base.Add(new TypedValue((int)type, obj));
}
public override string ToString()
{
return ((ResultBuffer)this).ToString();
}
public static implicit operator TypedValue[](ResultList rlst)
{
return rlst.ToArray();
}
public static implicit operator ResultBuffer(ResultList rlst)
{
return new ResultBuffer(rlst.ToArray());
}
public static implicit operator SelectionFilter(ResultList rlst)
{
return new SelectionFilter(rlst.ToArray());
}
}
}
Test Code
PromptSelectionResult res4 =
ed.SelectAll(
new ResultList
{
{-4,"<or"},
{-4,"<and"},
{0, "Line"},
{8, "01"},
{-4,"and>"},
{-4,"<and"},
{0, "Circle"},
{8, "02"},
{-4,"and>"},
{-4,"or>"}
});
-
Another version
using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System.Collections;
namespace TlsCad.Collections
{
/// <summary>
/// TypedValue Tree
/// </summary>
///
public enum ResultType
{
Node,
List,
DottedPair,
RelationalOperator,
LogicalOperator,
}
public class ResultTree : IEnumerable
{
ResultType _type;
TypedValue _value;
List<ResultTree> _lst = new List<ResultTree>();
public ResultTree this[int index]
{
get
{
if (_lst.Count==0)
{
if(index==0)
{
return this;
}
}
else
{
if (index>=0 && index < _lst.Count)
{
return _lst[index];
}
}
return null;
}
}
public TypedValue TypedValue
{
get { return _value; }
}
public List<ResultTree> Nodes
{
get { return _lst; }
}
public ResultType Type
{
get { return _type; }
}
public ResultTree()
{
_type = ResultType.Node;
}
public ResultTree(TypedValue value)
:this()
{
_value = value;
}
public ResultTree(int typeCode, object obj)
: this(new TypedValue(typeCode, obj))
{ }
public ResultTree(LispDataType type, object obj)
: this(new TypedValue((int)type, obj))
{ }
public ResultTree(DxfCode type, object obj)
: this(new TypedValue((int)type, obj))
{ }
public ResultTree(string operatorContext, bool isLogicalOperator)
{
_type = isLogicalOperator ? ResultType.LogicalOperator : ResultType.RelationalOperator;
_value = new TypedValue(-4, operatorContext);
}
public ResultTree(string operatorContext)
: this(operatorContext, true)
{ }
public ResultTree(ResultType type)
{
_type = type;
}
public void Add(TypedValue value)
{
_lst.Add(new ResultTree(value));
}
public void Add(int typeCode, object obj)
{
_lst.Add(new ResultTree(typeCode, obj));
}
public void Add(LispDataType type, object obj)
{
_lst.Add(new ResultTree(type, obj));
}
public void Add(DxfCode type, object obj)
{
_lst.Add(new ResultTree(type, obj));
}
public void Add(ResultTree rt)
{
_lst.Add(rt);
}
public void Add(short value)
{
_lst.Add(new ResultTree(LispDataType.Int16, value));
}
public void Add(int value)
{
_lst.Add(new ResultTree(LispDataType.Int32, value));
}
public void Add(double value)
{
_lst.Add(new ResultTree(LispDataType.Double, value));
}
public void Add(string value)
{
_lst.Add(new ResultTree(LispDataType.Text, value));
}
public void Add(Point2d value)
{
_lst.Add(new ResultTree(LispDataType.Point2d, value));
}
public void Add(Point3d value)
{
_lst.Add(new ResultTree(LispDataType.Point3d, value));
}
public void Add(ObjectId value)
{
_lst.Add(new ResultTree(LispDataType.ObjectId, value));
}
public void Add(SelectionSet value)
{
_lst.Add(new ResultTree(LispDataType.SelectionSet, value));
}
public static implicit operator SelectionFilter(ResultTree rtree)
{
return new SelectionFilter(rtree.ToArray());
}
public static implicit operator ResultBuffer(ResultTree rtree)
{
return new ResultBuffer(rtree.ToArray());
}
public TypedValue[] ToArray()
{
List<TypedValue> values = new List<TypedValue>();
GetValues(values);
return values.ToArray();
}
private void GetValues(List<TypedValue> values)
{
switch (_type)
{
case ResultType.Node:
if (_lst.Count == 0)
{
values.Add(_value);
}
else
{
_lst.ForEach(rtree => rtree.GetValues(values));
}
break;
case ResultType.List:
values.Add(new TypedValue((int)LispDataType.ListBegin));
_lst.ForEach(rtree => rtree.GetValues(values));
values.Add(new TypedValue((int)LispDataType.ListEnd));
break;
case ResultType.DottedPair:
values.Add(new TypedValue((int)LispDataType.ListBegin));
_lst.ForEach(rtree => rtree.GetValues(values));
values.Add(new TypedValue((int)LispDataType.DottedPair));
break;
case ResultType.RelationalOperator:
values.Add(_value);
_lst.ForEach(rtree => rtree.GetValues(values));
break;
case ResultType.LogicalOperator:
values.Add(new TypedValue(-4, "<" + _value.Value));
_lst.ForEach(rtree => rtree.GetValues(values));
values.Add(new TypedValue(-4, _value.Value + ">"));
break;
}
}
#region IEnumerable 成员
IEnumerator IEnumerable.GetEnumerator()
{
return _lst.GetEnumerator();
}
#endregion
}
}
The complete test code
[CommandMethod("t9")]
public static void Test9()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptSelectionResult res1 =
ed.SelectAll(
new ResultTree
{
new ResultTree(">,>,*",false)
{
{10, new Point3d()}
},
new ResultTree("<,<,*",false)
{
{10,new Point3d(10,10,0)}
}
});
PromptSelectionResult res2 =
ed.SelectAll(
new ResultList
{
{-4,">,>,*"},
{10, new Point3d()},
{-4,"<,<,*"},
{10,new Point3d(10,10,0)}
});
PromptSelectionResult res3 =
ed.SelectAll(
new ResultTree("or")
{
new ResultTree("and")
{
{0, "Line"},
{8, "01"}
},
new ResultTree("and")
{
{0, "Circle"},
{8, "02"}
}
});
PromptSelectionResult res4 =
ed.SelectAll(
new ResultList
{
{-4,"<or"},
{-4,"<and"},
{0, "Line"},
{8, "01"},
{-4,"and>"},
{-4,"<and"},
{0, "Circle"},
{8, "02"},
{-4,"and>"},
{-4,"or>"}
});
}
[CommandMethod("t10")]
public static void Test10()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityResult res = ed.GetEntity("Select a Entity:");
using (DBTransaction tr = new DBTransaction())
{
tr.OpenRegAppTable(OpenMode.ForWrite);
tr.RegApp("MyApp");
Entity ent = tr.GetObject(res.ObjectId, OpenMode.ForWrite) as Entity;
ent.XData =
new ResultList
{
{1001, "MyApp"},
{1000, "This is a Test"},
{DxfCode.ExtendedDataInteger16, 12}
};
}
}
[LispFunction("lsptest1")]
public static ResultBuffer LTest1(ResultBuffer rb)
{
ResultTree rtree =
new ResultTree(ResultType.List)
{
1,
new ResultTree(ResultType.DottedPair)
{
10,
new Point3d(10, 10, 0)
}
};
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
return rtree;
}
-
Nice work! That's similar to this http://www.theswamp.org/index.php?topic=14495.msg186823#msg186823
I think the goal was to remove the need to remember the DXF group codes or having to look up from an Enum,
and maybe something like AddEntityFilter or AddLayerFilter would make building the filter more intuitive
-
ding
-
Nice work! That's similar to this http://www.theswamp.org/index.php?topic=14495.msg186823#msg186823
I think the goal was to remove the need to remember the DXF group codes or having to look up from an Enum,
and maybe something like AddEntityFilter or AddLayerFilter would make building the filter more intuitive
However, the complex filtering is not a good realization of
For example, to select "01-layer line" or "02-layer Circle"
Can look at the code ResultTree class
-
I agree, it would be difficult to build complex selection set filters with a user friendly class.
I like your ResultTree class, that's great work!
-
I agree, it would be difficult to build complex selection set filters with a user friendly class.
I like your ResultTree class, that's great work!
Thanks Daniel, I am truly honored.
-
Operator Overloading
This is more fun,:)
using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System.Collections;
namespace TlsCad.Collections
{
public enum ResultType
{
Node,
List,
DottedPair,
RelationalOperator,
LogicalOperator,
}
/// <summary>
/// TypedValue Tree
/// </summary>
public class ResultTree : IEnumerable
{
ResultType _type;
TypedValue _value;
List<ResultTree> _lst = new List<ResultTree>();
public ResultTree this[int index]
{
get
{
if (_lst.Count==0)
{
if(index==0)
{
return this;
}
}
else
{
if (index>=0 && index < _lst.Count)
{
return _lst[index];
}
}
return null;
}
}
public TypedValue TypedValue
{
get { return _value; }
}
public List<ResultTree> Nodes
{
get { return _lst; }
}
public ResultType Type
{
get { return _type; }
}
#region IEnumerable 成员
IEnumerator IEnumerable.GetEnumerator()
{
return _lst.GetEnumerator();
}
#endregion
public ResultTree()
{
_type = ResultType.Node;
}
public ResultTree(TypedValue value)
:this()
{
_value = value;
}
public ResultTree(int typeCode, object obj)
: this(new TypedValue(typeCode, obj))
{ }
public ResultTree(LispDataType type, object obj)
: this(new TypedValue((int)type, obj))
{ }
public ResultTree(DxfCode type, object obj)
: this(new TypedValue((int)type, obj))
{ }
public ResultTree(string operatorContext, bool isLogicalOperator)
{
_type = isLogicalOperator ? ResultType.LogicalOperator : ResultType.RelationalOperator;
_value = new TypedValue(-4, operatorContext);
}
public ResultTree(string operatorContext)
: this(operatorContext, true)
{ }
public ResultTree(ResultType type)
{
_type = type;
}
public void Add(TypedValue value)
{
_lst.Add(new ResultTree(value));
}
public void Add(int typeCode, object obj)
{
_lst.Add(new ResultTree(typeCode, obj));
}
public void Add(LispDataType type, object obj)
{
_lst.Add(new ResultTree(type, obj));
}
public void Add(DxfCode type, object obj)
{
_lst.Add(new ResultTree(type, obj));
}
public void Add(ResultTree rt)
{
_lst.Add(rt);
}
public void Add(short value)
{
_lst.Add(new ResultTree(LispDataType.Int16, value));
}
public void Add(int value)
{
_lst.Add(new ResultTree(LispDataType.Int32, value));
}
public void Add(double value)
{
_lst.Add(new ResultTree(LispDataType.Double, value));
}
public void Add(string value)
{
_lst.Add(new ResultTree(LispDataType.Text, value));
}
public void Add(Point2d value)
{
_lst.Add(new ResultTree(LispDataType.Point2d, value));
}
public void Add(Point3d value)
{
_lst.Add(new ResultTree(LispDataType.Point3d, value));
}
public void Add(ObjectId value)
{
_lst.Add(new ResultTree(LispDataType.ObjectId, value));
}
public void Add(SelectionSet value)
{
_lst.Add(new ResultTree(LispDataType.SelectionSet, value));
}
private void GetValues(List<TypedValue> values)
{
switch (_type)
{
case ResultType.Node:
if (_lst.Count == 0)
{
values.Add(_value);
}
else
{
_lst.ForEach(rtree => rtree.GetValues(values));
}
break;
case ResultType.List:
values.Add(new TypedValue((int)LispDataType.ListBegin));
_lst.ForEach(rtree => rtree.GetValues(values));
values.Add(new TypedValue((int)LispDataType.ListEnd));
break;
case ResultType.DottedPair:
values.Add(new TypedValue((int)LispDataType.ListBegin));
_lst.ForEach(rtree => rtree.GetValues(values));
values.Add(new TypedValue((int)LispDataType.DottedPair));
break;
case ResultType.RelationalOperator:
values.Add(_value);
_lst.ForEach(rtree => rtree.GetValues(values));
break;
case ResultType.LogicalOperator:
values.Add(new TypedValue(-4, "<" + _value.Value));
_lst.ForEach(rtree => rtree.GetValues(values));
values.Add(new TypedValue(-4, _value.Value + ">"));
break;
}
}
public TypedValue[] ToArray()
{
List<TypedValue> values = new List<TypedValue>();
GetValues(values);
return values.ToArray();
}
public static implicit operator SelectionFilter(ResultTree rtree)
{
return new SelectionFilter(rtree.ToArray());
}
public static implicit operator ResultBuffer(ResultTree rtree)
{
return new ResultBuffer(rtree.ToArray());
}
public override string ToString()
{
return ((ResultBuffer)this).ToString();
}
private void MakeLogicalOperator(string operatorContext, ResultTree res)
{
if (_type == ResultType.LogicalOperator && _value.Value.ToString() == operatorContext)
{
_lst.ForEach(rtree => res.Add(rtree));
}
else
{
res.Add(this);
}
}
public static ResultTree operator !(ResultTree rt1)
{
ResultTree rt = new ResultTree("not") { rt1 };
return rt;
}
public static ResultTree operator &(ResultTree rt1, ResultTree rt2)
{
ResultTree rt = new ResultTree("and");
rt1.MakeLogicalOperator("and", rt);
rt2.MakeLogicalOperator("and", rt);
return rt;
}
public static ResultTree operator |(ResultTree rt1, ResultTree rt2)
{
ResultTree rt = new ResultTree("or");
rt1.MakeLogicalOperator("or", rt);
rt2.MakeLogicalOperator("or", rt);
return rt;
}
public static ResultTree operator ^(ResultTree rt1, ResultTree rt2)
{
return
new ResultTree("xor")
{
rt1,
rt2
};
}
}
}
test code
ResultTree rt =
new ResultTree(0, "Line") & new ResultTree(8, "01") & !new ResultTree(10, new Point3d())
|
new ResultTree(0, "Circle") & new ResultTree(8, "02");
Application.ShowAlertDialog(rt.ToString());
-
I've been testing selectionsets versus objectIds for a selectall.
If you are only checking for types (circle arc etc) the objectId method is always faster.
However when you also check for layers etc, the selectionset is faster.
The function below is fairly easy to use
static ObjectIdCollection SelectAll(string dxfNames)
{
dxfNames = dxfNames.ToUpper();
string[] dxf=dxfNames.Split(new char[] {','},StringSplitOptions.RemoveEmptyEntries);
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
ObjectIdCollection ids = new ObjectIdCollection();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
DBDictionary ld = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
Layout layout = null;
foreach (DBDictionaryEntry l in ld)
{
layout = tr.GetObject(l.m_value, OpenMode.ForRead) as Layout;
BlockTableRecord space = (BlockTableRecord)tr.GetObject
(layout.BlockTableRecordId, OpenMode.ForRead);
foreach (ObjectId id in space)
{
foreach (string name in dxf)
{
if (id.ObjectClass.DxfName == name)
{
ids.Add(id);
break;
}
}
}
}
tr.Commit();
}
return ids;
} // end SelectAll
and how to call it
move = Matrix3d.Displacement(new Vector3d(0, -1, 0));
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (ObjectId id in SelectAll("Line,Arc,Circle,ellipse"))
{
c = (Curve)tr.GetObject(id, OpenMode.ForRead);
if (c.Layer == "0")
{
count++;
c.UpgradeOpen();
c.TransformBy(move);
}
}
tr.Commit();
}
-
what about this? :lol:
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
[assembly: CommandClass(typeof(ExecMethod.Commands))]
namespace ExecMethod
{
public class ObjectIdDictionary : Dictionary<string, List<ObjectId>>
{
private ObjectIdDictionary() { }
public ObjectIdDictionary(Database database, ObjectId spaceid)
{
AcDb.TransactionManager manager = database.TransactionManager;
using (Transaction transaction = manager.StartTransaction())
{
BlockTableRecord blockTableRecord =
transaction.GetObject(spaceid, OpenMode.ForRead)
as BlockTableRecord;
foreach (ObjectId e in blockTableRecord)
{
string key = e.ObjectClass.DxfName;
if (this.ContainsKey(key))
this[key].Add(e);
else
this.Add(key, new List<ObjectId> { e });
}
transaction.Commit();
}
}
}
public static class Commands
{
[CommandMethod("doit")]
static public void doit()
{
Database database = HostApplicationServices.WorkingDatabase;
ObjectIdDictionary dict = new ObjectIdDictionary(database, database.CurrentSpaceId);
AcDb.TransactionManager manager = database.TransactionManager;
using (Transaction transaction = manager.StartTransaction())
{
if (dict.ContainsKey("POINT"))
{
foreach (ObjectId e in dict["POINT"])
{
DBPoint o = transaction.GetObject(e, OpenMode.ForWrite) as DBPoint;
o.ColorIndex = 1;
}
}
if (dict.ContainsKey("LINE"))
{
foreach (ObjectId e in dict["LINE"])
{
Line o = transaction.GetObject(e, OpenMode.ForWrite) as Line;
o.ColorIndex = 2;
}
}
if (dict.ContainsKey("LWPOLYLINE"))
{
foreach (ObjectId e in dict["LWPOLYLINE"])
{
Polyline o = transaction.GetObject(e, OpenMode.ForWrite) as Polyline;
o.ColorIndex = 3;
}
}
if (dict.ContainsKey("CIRCLE"))
{
foreach (ObjectId e in dict["CIRCLE"])
{
Circle o = transaction.GetObject(e, OpenMode.ForWrite) as Circle;
o.ColorIndex = 4;
}
transaction.Commit();
}
}
}
}
}
-
I agree, but only through AC2010
Test it use Linq :-)
[CommandMethod("t8")]
public static void Test8()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
var dict = from ObjectId id in btr
group id by id.ObjectClass.DxfName;
foreach (var ids in dict)
{
switch (ids.Key)
{
case "LINE":
foreach (var id in ids)
{
Entity ent = id.GetObject(OpenMode.ForWrite) as Entity;
ent.ColorIndex = 1;
}
break;
case "CIRCLE":
foreach (var id in ids)
{
Entity ent = id.GetObject(OpenMode.ForWrite) as Entity;
ent.ColorIndex = 3;
}
break;
}
}
tr.Commit();
}
}
-
Ha! that is cool 8-)
-
The linq is about the same as Daniel's dictionary method (sometimes slightly slower)
Both are faster than mine which seems to point to objectidcollections being a bit slow.
It seems the dwg gets bigger, so I think you need to delete the dictionary after using it.
-
Bryco, compare this to yours for speed
static ObjectIdCollection SelectAll(string dxfNames)
{
dxfNames = dxfNames.ToUpper();
List<String> dxf = new List<string>
(dxfNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
Document doc = AcAp.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
ObjectIdCollection ids = new ObjectIdCollection();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
DBDictionary ld = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
Layout layout = null;
foreach (DBDictionaryEntry l in ld)
{
layout = tr.GetObject(l.m_value, OpenMode.ForRead) as Layout;
BlockTableRecord space = (BlockTableRecord)tr.GetObject
(layout.BlockTableRecordId, OpenMode.ForRead);
foreach (ObjectId id in space)
{
if (dxf.Contains(id.ObjectClass.DxfName))
{
ids.Add(id);
}
}
}
tr.Commit();
}
return ids;
} // end SelectAll
-
That's the one I compared it to. I guess a collection is in inherently slower as it adds indexing.
-
I had changed your inner loop, I just wondered if it made a difference
-
SelectionSet count w/ 2 types = 44 time=2880
using this filter filter = new TypedValue[] { new TypedValue(0, "Line,Arc,Circle,ellipse"), new TypedValue(8, "0") };
Objectid count w/ 2 types selectall = 44 time=10740
using "Line,Arc,Circle,ellipse" and then selectall as I wrote then checking for layer 0
Objectid count w/ 2 types selectall2 = 44 time=10940
using "Line,Arc,Circle,ellipse" and then selectall as Daniel wrote then checking for layer 0
dictionary = 44 time=7900 Daniel's dictioary
dictionary = 44 time=7940 xsfhlzh's Linq
There are almost 90000 entities in the dwg.
Daniel your version looks like it would do better but it still must go through the same amount of steps