AutoCAD has supported the eXtended Data for long time, back to the ADS era. In the AutoCAD .NET world, those functionalities regarding the XData manipulations and even those extended DXF codes are wrapped nicely into some classes, structs, methods and enums.
However, because of the different syntaxes in the new AutoCAD .NET and the old ADS, even for people coming from the ADS time and using those old ResultBuffer a lot, they may still be confused about some classes, methods, and enum values as far as XData and ResultBuffer are concerned.
Previously, we added various XData types to a single picked AutoCAD entity. In this post, let’s read out those XData with various types and assign them to variables of proper types.
[CommandMethod("ReadXData")]
public static void ReadXData_Method()
{
const string TestAppName = "XDataAppName1";
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
try
{
PromptEntityResult prEntRes = ed.GetEntity("Select an Entity");
if (prEntRes.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Entity ent = (Entity)tr.GetObject(prEntRes.ObjectId, OpenMode.ForRead);
ResultBuffer rb = ent.GetXDataForApplication(TestAppName);
if (rb != null)
{
TypedValue[] rvArr = rb.AsArray();
foreach (TypedValue tv in rvArr)
{
switch ((DxfCode)tv.TypeCode)
{
case DxfCode.ExtendedDataRegAppName:
string appName = (string)tv.Value;
ed.WriteMessage("\nXData of appliation name (1001) {0}:", appName);
break;
case DxfCode.ExtendedDataAsciiString:
string asciiStr = (string)tv.Value;
ed.WriteMessage("\n\tAscii string (1000): {0}", asciiStr);
break;
case DxfCode.ExtendedDataLayerName:
string layerName = (string)tv.Value;
ed.WriteMessage("\n\tLayer name (1003): {0}", layerName);
break;
case DxfCode.ExtendedDataBinaryChunk:
Byte[] chunk = tv.Value as Byte[];
string chunkText = Encoding.ASCII.GetString(chunk);
ed.WriteMessage("\n\tBinary chunk (1004): {0}", chunkText);
break;
case DxfCode.ExtendedDataHandle:
ed.WriteMessage("\n\tObject handle (1005): {0}", tv.Value);
break;
case DxfCode.ExtendedDataXCoordinate:
Point3d pt = (Point3d)tv.Value;
ed.WriteMessage("\n\tPoint (1010): {0}", pt.ToString());
break;
case DxfCode.ExtendedDataWorldXCoordinate:
Point3d pt1 = (Point3d)tv.Value;
ed.WriteMessage("\n\tWorld point (1011): {0}", pt1.ToString());
break;
case DxfCode.ExtendedDataWorldXDisp:
Point3d pt2 = (Point3d)tv.Value;
ed.WriteMessage("\n\tDisplacement (1012): {0}", pt2.ToString());
break;
case DxfCode.ExtendedDataWorldXDir:
Point3d pt3 = (Point3d)tv.Value;
ed.WriteMessage("\n\tDirection (1013): {0}", pt3.ToString());
break;
case DxfCode.ExtendedDataControlString:
string ctrStr = (string)tv.Value;
ed.WriteMessage("\n\tControl string (1002): {0}", ctrStr);
break;
case DxfCode.ExtendedDataReal:
double realValue = (double)tv.Value;
ed.WriteMessage("\n\tReal (1040): {0}", realValue);
break;
case DxfCode.ExtendedDataDist:
double dist = (double)tv.Value;
ed.WriteMessage("\n\tDistance (1041): {0}", dist);
break;
case DxfCode.ExtendedDataScale:
double scale = (double)tv.Value;
ed.WriteMessage("\n\tScale (1042): {0}", scale);
break;
case DxfCode.ExtendedDataInteger16:
Int16 int16 = (short)tv.Value;
ed.WriteMessage("\n\tInt16 (1070): {0}", int16);
break;
case DxfCode.ExtendedDataInteger32:
Int32 int32 = (Int32)tv.Value;
ed.WriteMessage("\n\tInt32 (1071): {0}", int32);
break;
default:
ed.WriteMessage("\n\tUnknown XData DXF code.");
break;
}
}
}
else
ed.WriteMessage("The entity does not have the {0} XData.", TestAppName);
tr.Commit();
}
}
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.ToString());
}
}
Here is he output in the AutoCAD command line window.
Command: ADDXDAta
Select an Entity to attach XDATA:
Command: READXDATA
Select an Entity:
XData of appliation name (1001) XDataAppName1:
Ascii string (1000): String1
Layer name (1003): 0
Binary chunk (1004): BinaryChunk
Object handle (1005): A53
Point (1010): (1.1,2.1,3.1)
World point (1011): (1.2,2.2,3.2)
Displacement (1012): (1.3,2.3,3.3)
Direction (1013): (1.4,2.4,3.4)
Control string (1002): {
Real (1040): 12345.6789
Distance (1041): 25.25
Scale (1042): 0.2
Control string (1002): }
Int16 (1070): 16
Int32 (1071): 32
The code seems simple and straightforward, but there are quite some tips and tricks there.
• The DBObject.GetXDataForApplication() method can retrieve the XData with the specified application name from a DBObject or Entity.
• All XData starts with the 1001 (DxfCode.ExtendedDataRegAppName) code.
• The XData Application Name can be registered through creating a RegAppTableRecord and adding it to the RegAppTable (another kind of AutoCAD symbol table).
• The ResultBuffer is a list of TypedValue which is a pair of type and value.
• The DxfCode.ExtendedDataLayerName enum value (with integer 1003) specifies that the value will be a layer name. Whether the layer has to present or not in the current database may need further exploration.
• The DxfCode.ExtendedDataBinaryChunk enum value (with integer 1004) specifies that the XData value will be some binary chunk. We will address it further in the future.
• The DxfCode.ExtendedDataHandle enum value (with integer 1005) specifies that the XData value is supposed to be a valid AutoCAD object handle. If it is not a good object handle or the object it references to has been deleted, the Audio command will report an error and the Fix option will set it as NULL or empty.
• The DxfCode.ExtendedDataXCoordinate enum value (with integer 1010) and the DxfCode.ExtendedDataWorldXCoordinate (with integer 1011) specify that the XData value will be a 3D point.
• When the two enum values (1010 or 1011) are specified as the XData type, their value objects should be of type Point3d.
• The DxfCode.ExtendedDataYCoordinate (1020) and the DxfCode.ExtendedDataZCoordinate (1030) enum values are there for other purposes. They should not be used in the TypedValue constructors. Otherwise, exceptions would just occur.
• The same apply to the ExtendedDataWorldYCoordinate (1021) and the ExtendedDataWorldYCoordinate (1031) enum values.
• Though the DxfCode.ExtendedDataWorldXDisp (1012) and the DxfCode.ExtendedDataWorldXDir (1013) indicate that the XData value should be a displacement, direction, or a vector, the TypedValue constructor does not accept a Vector3d object! They still only accept the type of Point3d!
• Once again, the DxfCode.ExtendedDataWorldYDisp(1022)/DxfCode.ExtendedDataWorldZDisp(1032) and DxfCode.ExtendedDataWorldYDir(1023)/DxfCode.ExtendedDataWorldZDir(1033) are there for other purposes. They should not be used in the TypedValue constructors. Otherwise, exceptions would just occur.
• The DxfCode.ExtendedDataControlString indicates that the XData value can be either "{" or “}” and the two symbols must be balanced in the whole XData group. They can be nested.
• The DxfCode.ExtendedDataReal (1040), DxfCode.ExtendedDataDist(1041), DxfCode.ExtendedDataScale, (1042), DxfCode.ExtendedDataInteger16 (1070) and DxfCode.ExtendedDataInteger32 (1071) are straightforward as their names suggest.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides project wizards in C#, VB.NET and CLI/Managed C++, and various item wizards such as Event Handlers, Command/LispFunction Definers, and Entity/Draw Jiggers in both C# and VB.NET, to help program AutoCAD addins.
Recent Comments