using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
/// This code serves to debunk the myth that
/// the OpenClosTransaction is 'faster' than
/// a standard Transaction. The fact is that
/// it is not significantly-faster when the
/// amount of data involved is large.
///
/// And, when the amount of data involved is
/// relatively-small, the question of which
/// is faster, is entirely moot.
namespace TransactionTest
{
public static class TestTransactionCommands
{
/// <summary>
/// Test standard transaction (AcTrTransaction)
/// </summary>
[CommandMethod( "TT1" )]
public static void TestAcTrTransaction()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using( Transaction tr = doc.TransactionManager.StartTransaction() )
{
BlockTableRecord btr = (BlockTableRecord)
tr.GetObject( db.CurrentSpaceId, OpenMode.ForRead );
RXClass dbPointClass
= RXClass
.GetClass( typeof( DBPoint
) );
int i = 0;
Stopwatch sw = Stopwatch.StartNew();
foreach( ObjectId id in btr )
{
if( id.ObjectClass == dbPointClass )
{
DBPoint p = (DBPoint) tr.GetObject( id, OpenMode.ForRead );
++i;
}
}
sw.Stop();
ed.WriteMessage( "\nAcTrTransaction: {0}", sw.ElapsedMilliseconds );
tr.Commit();
}
}
/// <summary>
/// Test OpenCloseTransaction
/// </summary>
[CommandMethod( "TT2" )]
public static void TestOpenCloseTransaction()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using( Transaction tr = doc.TransactionManager.StartOpenCloseTransaction() )
{
BlockTableRecord btr = (BlockTableRecord)
tr.GetObject( db.CurrentSpaceId, OpenMode.ForRead );
RXClass dbPointClass
= RXClass
.GetClass( typeof( DBPoint
) );
int i = 0;
Stopwatch sw = Stopwatch.StartNew();
foreach( ObjectId id in btr )
{
if( id.ObjectClass == dbPointClass )
{
DBPoint p = (DBPoint) tr.GetObject( id, OpenMode.ForRead );
++i;
}
}
sw.Stop();
ed.WriteMessage( "\nOpenCloseTransaction: {0}", sw.ElapsedMilliseconds );
tr.Commit();
}
}
/// <summary>
/// Command to generate random DBPoints used as test data
/// </summary>
[CommandMethod( "RNDPOINTS" )]
public static void RndPoints()
{
PromptDoubleOptions pdo
= new PromptDoubleOptions
( "\nNumber of points: " ); pdo.AllowZero = false;
pdo.AllowNegative = false;
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
PromptDoubleResult pdr = doc.Editor.GetDouble( pdo );
if( pdr.Status != PromptStatus.OK )
return;
int cnt = Convert.ToInt32( pdr.Value );
using( Transaction tr = doc.TransactionManager.StartTransaction() )
{
BlockTableRecord btr = (BlockTableRecord)
doc.Database.CurrentSpaceId.GetObject( OpenMode.ForWrite );
var points = GetRandomPoints( cnt, 10000.0 );
foreach( Point3d pt in points )
{
DBPoint dbp
= new DBPoint
( pt
); btr.AppendEntity( dbp );
tr.AddNewlyCreatedDBObject( dbp, true );
}
tr.Commit();
}
}
/// <summary>
/// Get an array of random Point3d dispersed in a
/// Cube or 2d square whose side length = scale.
/// If flat is true, all resulting points are in
/// the XY plane.
/// </summary>
static IEnumerable<Point3d> GetRandomPoints( long count, double scale, bool flat = false )
{
Random rnd
= new Random
(); if( flat )
{
for( long i = 0; i < count; i++ )
{
yield return new Point3d
( rnd.NextDouble() * scale,
rnd.NextDouble() * scale,
0.0 );
}
}
else
{
for( long i = 0; i < count; i++ )
{
yield return new Point3d
( rnd.NextDouble() * scale,
rnd.NextDouble() * scale,
rnd.NextDouble() * scale );
}
}
}
}
}