About the Simple point plug-in data source Sample
[C#]
SimplePointDataset.cs
using System;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
namespace ESRI.ArcGIS.Samples.SimplePointPlugin
{
/// <summary>
/// Summary description for SimplePointDataset.
/// </summary>
[ComVisible(false)]
internal class SimplePointDataset: IPlugInDatasetHelper, IPlugInDatasetInfo
{
private string m_wkspString, m_datasetString;
private IEnvelope m_bound;
private string m_fullPath;
public SimplePointDataset(string wkspString, string datasetString)
{
//HIGHLIGHT: constructor checks valid workspace string path and dataset name
m_wkspString = wkspString;
m_fullPath = System.IO.Path.Combine(wkspString, datasetString);
if (System.IO.Path.HasExtension(datasetString))
m_datasetString = System.IO.Path.GetFileNameWithoutExtension(datasetString);
else
{
m_datasetString = datasetString;
m_fullPath += ".csp"; //add the extension
}
}
#region IPlugInDatasetHelper Members
public IEnvelope Bounds
{
get
{
if (this.DatasetType == esriDatasetType.esriDTTable)
return null;
if (m_bound == null)
{
#region use cursor go through records, or we can parse the file directly
m_bound = new EnvelopeClass();
m_bound.SpatialReference = this.spatialReference;
IFields fields = this.get_Fields(0);
int[] fieldMapArray = new int[fields.FieldCount];
for (int i = 0; i < fields.FieldCount; i++)
fieldMapArray[i] = -1; //shape field always ignored?
double x1 = 999999, y1 = 999999, x2 = 0, y2 = 0; //assumes all positive value in the file
//Set with appropriate geometry
IGeometry workGeom;
IPlugInCursorHelper cursor;
if (this.DatasetType == esriDatasetType.esriDTFeatureDataset)
{
workGeom = new PolygonClass();
cursor = this.FetchAll(2, null, fieldMapArray);
}
else
{
workGeom = new PointClass();
cursor = this.FetchAll(0, null, fieldMapArray);
}
workGeom.SpatialReference = this.spatialReference;
while (true)
{
try
{
cursor.QueryShape(workGeom);
if (workGeom.Envelope.XMin < x1)
x1 = workGeom.Envelope.XMin;
if (workGeom.Envelope.XMax > x2)
x2 = workGeom.Envelope.XMax;
if (workGeom.Envelope.YMin < y1)
y1 = workGeom.Envelope.YMin;
if (workGeom.Envelope.YMax > y2)
y2 = workGeom.Envelope.YMax;
cursor.NextRecord();
}
catch (COMException comEx)
{
System.Diagnostics.Debug.WriteLine(comEx.Message);
break; //catch E_FAIL when cursor reaches the end, exit loop
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
m_bound.PutCoords(x1, y1, x2, y2);
#endregion
}
//HIGHLIGHT: return clone envelope for bound
IClone cloneEnv = (IClone)m_bound;
return (IEnvelope)cloneEnv.Clone();
}
}
public int get_ShapeFieldIndex(int ClassIndex)
{
//add table to ArcMap via add data dialog calls this method, so if it's a table
//you must return -1 or else ArcMap crashes
if (this.DatasetType == esriDatasetType.esriDTTable)
return -1;
return 1;
}
public IFields get_Fields(int ClassIndex)
{
IFieldEdit fieldEdit;
IFields fields;
IFieldsEdit fieldsEdit;
IObjectClassDescription fcDesc;
if (this.DatasetType == esriDatasetType.esriDTTable)
fcDesc = new ObjectClassDescriptionClass();
else
fcDesc = new FeatureClassDescriptionClass();
fields = fcDesc.RequiredFields;
fieldsEdit = (IFieldsEdit)fields;
fieldEdit = new FieldClass();
fieldEdit.Length_2 = 1;
fieldEdit.Name_2 = "ColumnOne";
fieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
fieldsEdit.AddField((IField)fieldEdit);
//HIGHLIGHT: Add extra int column
fieldEdit = new FieldClass();
fieldEdit.Name_2 = "Extra";
fieldEdit.Type_2 = esriFieldType.esriFieldTypeInteger;
fieldsEdit.AddField((IField)fieldEdit);
//HIGHLIGHT: Set shape field geometry definition
if (this.DatasetType != esriDatasetType.esriDTTable)
{
IField field = fields.get_Field(fields.FindField("Shape"));
fieldEdit = (IFieldEdit)field;
IGeometryDefEdit geomDefEdit = (IGeometryDefEdit)field.GeometryDef;
geomDefEdit.GeometryType_2 = geometryTypeByID(ClassIndex);
ISpatialReference shapeSRef = this.spatialReference;
#region M & Z
//M
if ((ClassIndex >= 3 && ClassIndex <=5) || ClassIndex >= 9)
{
geomDefEdit.HasM_2 = true;
shapeSRef.SetMDomain(0, 1000);
}
else
geomDefEdit.HasM_2 = false;
//Z
if (ClassIndex >= 6)
{
geomDefEdit.HasZ_2 = true;
shapeSRef.SetZDomain(0, 1000);
}
else
geomDefEdit.HasZ_2 = false;
#endregion
geomDefEdit.SpatialReference_2 = shapeSRef;
}
return fields;
}
public string get_ClassName(int Index)
{
if (Index % 3 == 0)
m_datasetString = "Point";
if (Index % 3 == 1)
m_datasetString = "Polyline";
if (Index % 3 == 2)
m_datasetString = "Polygon";
if ((Index >= 3 && Index < 6) || Index >= 9)
m_datasetString += "M";
if (Index >= 6)
m_datasetString += "Z";
return m_datasetString;
}
public int get_OIDFieldIndex(int ClassIndex)
{
return 0;
}
public int ClassCount
{
get
{
if (this.DatasetType == esriDatasetType.esriDTFeatureDataset)
return 12;
return 1;
}
}
public int get_ClassIndex(string Name)
{
for (int i = 0; i < this.ClassCount; i++)
{
if (Name.Equals(this.get_ClassName(i)))
return i;
}
return -1;
}
#region Fetching - returns cursor //HIGHLIGHT: Fetching
public IPlugInCursorHelper FetchAll(int ClassIndex, string WhereClause, object FieldMap)
{
try
{
SimplePointCursor allCursor =
new SimplePointCursor(m_fullPath, this.get_Fields(ClassIndex), -1,
(System.Array)FieldMap, null, this.geometryTypeByID(ClassIndex));
setMZ(allCursor, ClassIndex);
return (IPlugInCursorHelper)allCursor;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
return null;
}
}
public IPlugInCursorHelper FetchByID(int ClassIndex, int ID, object FieldMap)
{
try
{
SimplePointCursor idCursor =
new SimplePointCursor(m_fullPath, this.get_Fields(ClassIndex), ID,
(System.Array)FieldMap, null, this.geometryTypeByID(ClassIndex));
setMZ(idCursor, ClassIndex);
return (IPlugInCursorHelper)idCursor;
}
catch (Exception ex) //will catch NextRecord error if it reaches EOF without finding a record
{
System.Diagnostics.Debug.WriteLine(ex.Message);
return null;
}
}
public IPlugInCursorHelper FetchByEnvelope(int ClassIndex, IEnvelope env, bool strictSearch, string WhereClause, object FieldMap)
{
if (this.DatasetType == esriDatasetType.esriDTTable)
return null;
//env passed in always has same spatial reference as the data
//for identify, it will check if search geometry intersect dataset bound
//but not ITable.Search(pSpatialQueryFilter, bRecycle) etc
//so here we should check if input env falls within extent
IEnvelope boundEnv = this.Bounds;
boundEnv.Project(env.SpatialReference);
if (boundEnv.IsEmpty)
return null; //or raise error?
try
{
SimplePointCursor spatialCursor = new SimplePointCursor(m_fullPath,
this.get_Fields(ClassIndex), -1,
(System.Array)FieldMap, env, this.geometryTypeByID(ClassIndex));
setMZ(spatialCursor, ClassIndex);
return (IPlugInCursorHelper)spatialCursor;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
return null;
}
}
#endregion
#endregion
#region IPlugInDatasetInfo Members
//HIGHLIGHT: IPlugInDatasetInfo - lightweight!
public string LocalDatasetName
{
get
{
return m_datasetString;
}
}
public string ShapeFieldName
{
get
{
if (this.DatasetType == esriDatasetType.esriDTTable)
return null;
return "Shape";
}
}
public esriDatasetType DatasetType
{
get
{
// return esriDatasetType.esriDTTable;
// return esriDatasetType.esriDTFeatureClass;
return esriDatasetType.esriDTFeatureDataset;
}
}
public esriGeometryType GeometryType
{
get
{
return geometryTypeByID(-1); //might not be always easy to get
}
}
#endregion
#region internal helper methods
private esriGeometryType geometryTypeByID(int ClassIndex)
{
if (this.DatasetType == esriDatasetType.esriDTTable)
return esriGeometryType.esriGeometryNull;
if (ClassIndex % 3 == 0)
return esriGeometryType.esriGeometryPoint;
else if (ClassIndex % 3 == 1)
return esriGeometryType.esriGeometryPolyline;
else
return esriGeometryType.esriGeometryPolygon;
}
private ISpatialReference spatialReference
{
get
{
if (this.DatasetType == esriDatasetType.esriDTTable)
return null;
//singleton
ISpatialReferenceFactory2 srefFact = new SpatialReferenceEnvironmentClass();
return srefFact.CreateProjectedCoordinateSystem
(Convert.ToInt32(esriSRProjCSType.esriSRProjCS_World_Robinson)); // WGS1984UTM_10N));
}
}
private void setMZ(SimplePointCursor sptCursor, int Index)
{
sptCursor.HasM = ((Index >= 3 && Index < 6) || Index >= 9);
sptCursor.HasZ = (Index >= 6);
}
#endregion
}
}
[Visual Basic .NET]
SimplePointDataset.vb
Imports Microsoft.VisualBasic
Imports System
Imports System.Runtime.InteropServices
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Geometry
''' <summary>
''' Summary description for SimplePointDataset.
''' </summary>
<ComVisible(False)> _
Friend Class SimplePointDataset
Implements IPlugInDatasetInfo, IPlugInDatasetHelper
#Region "Class members"
Private m_wkspString, m_datasetString As String
Private m_bound As IEnvelope
Private m_fullPath As String
#End Region
#Region "Class constructor"
Public Sub New(ByVal wkspString As String, ByVal datasetString As String)
'HIGHLIGHT: constructor checks valid workspace string path and dataset name
m_wkspString = wkspString
m_fullPath = System.IO.Path.Combine(wkspString, datasetString)
If System.IO.Path.HasExtension(datasetString) Then
m_datasetString = System.IO.Path.GetFileNameWithoutExtension(datasetString)
Else
m_datasetString = datasetString
m_fullPath &= ".csp" 'add the extension
End If
End Sub
#End Region
#Region "IPlugInDatasetInfo Members "
'HIGHLIGHT: IPlugInDatasetInfo - lightweight!
Public ReadOnly Property LocalDatasetName() As String Implements IPlugInDatasetInfo.LocalDatasetName
Get
Return m_datasetString
End Get
End Property
Public ReadOnly Property ShapeFieldName() As String Implements IPlugInDatasetInfo.ShapeFieldName
Get
If Me.DatasetType = esriDatasetType.esriDTTable Then
Return Nothing
End If
Return "Shape"
End Get
End Property
Public ReadOnly Property DatasetType() As esriDatasetType Implements IPlugInDatasetInfo.DatasetType
Get
' return esriDatasetType.esriDTTable;
' return esriDatasetType.esriDTFeatureClass;
Return esriDatasetType.esriDTFeatureDataset
End Get
End Property
Public ReadOnly Property GeometryType() As esriGeometryType Implements IPlugInDatasetInfo.GeometryType
Get
Return geometryTypeByID(-1) 'might not be always easy to get
End Get
End Property
#End Region
#Region "IPlugInDatasetHelper Members"
Public ReadOnly Property Bounds() As ESRI.ArcGIS.Geometry.IEnvelope Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.Bounds
Get
If Me.DatasetType = esriDatasetType.esriDTTable Then
Return Nothing
End If
If m_bound Is Nothing Then
' #Region "use cursor go through records, or we can parse the file directly"
m_bound = New EnvelopeClass()
m_bound.SpatialReference = Me.spatialReference
Dim flds As IFields = Me.Fields(0)
Dim fieldMapArray As Integer() = New Integer(flds.FieldCount - 1) {}
Dim i As Integer = 0
Do While i < flds.FieldCount
fieldMapArray(i) = -1 'shape field always ignored?
i += 1
Loop
Dim x1 As Double = 999999, y1 As Double = 999999, x2 As Double = 0, y2 As Double = 0 'assumes all positive value in the file
'Set with appropriate geometry
Dim workGeom As IGeometry
Dim cursor As IPlugInCursorHelper
If Me.DatasetType = esriDatasetType.esriDTFeatureDataset Then
workGeom = New PolygonClass()
cursor = Me.FetchAll(2, Nothing, fieldMapArray)
Else
workGeom = New PointClass()
cursor = Me.FetchAll(0, Nothing, fieldMapArray)
End If
workGeom.SpatialReference = Me.spatialReference
Do While True
Try
cursor.QueryShape(workGeom)
If workGeom.Envelope.XMin < x1 Then
x1 = workGeom.Envelope.XMin
End If
If workGeom.Envelope.XMax > x2 Then
x2 = workGeom.Envelope.XMax
End If
If workGeom.Envelope.YMin < y1 Then
y1 = workGeom.Envelope.YMin
End If
If workGeom.Envelope.YMax > y2 Then
y2 = workGeom.Envelope.YMax
End If
cursor.NextRecord()
Catch comEx As COMException
System.Diagnostics.Debug.WriteLine(comEx.Message)
Exit Do 'catch E_FAIL when cursor reaches the end, exit loop
Catch ex As Exception
System.Diagnostics.Debug.WriteLine(ex.Message)
End Try
Loop
m_bound.PutCoords(x1, y1, x2, y2)
' #End Region
End If
'HIGHLIGHT: return clone envelope for bound
Dim cloneEnv As IClone = CType(m_bound, IClone)
Return CType(cloneEnv.Clone(), IEnvelope)
End Get
End Property
Public ReadOnly Property ClassCount() As Integer Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.ClassCount
Get
If Me.DatasetType = esriDatasetType.esriDTFeatureDataset Then
Return 12
End If
Return 1
End Get
End Property
Public ReadOnly Property ClassIndex(ByVal Name As String) As Integer Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.ClassIndex
Get
Dim i As Integer = 0
Do While i < Me.ClassCount
If Name.Equals(Me.ClassName(i)) Then
Return i
End If
i += 1
Loop
Return -1
End Get
End Property
Public ReadOnly Property ClassName(ByVal Index As Integer) As String Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.ClassName
Get
If Index Mod 3 = 0 Then
m_datasetString = "Point"
End If
If Index Mod 3 = 1 Then
m_datasetString = "Polyline"
End If
If Index Mod 3 = 2 Then
m_datasetString = "Polygon"
End If
If (Index >= 3 AndAlso Index < 6) OrElse Index >= 9 Then
m_datasetString &= "M"
End If
If Index >= 6 Then
m_datasetString &= "Z"
End If
Return m_datasetString
End Get
End Property
#Region "Fetching - returns cursor" 'HIGHLIGHT: Fetching
Public Function FetchAll(ByVal ClassIndex As Integer, ByVal WhereClause As String, ByVal FieldMap As Object) As ESRI.ArcGIS.Geodatabase.IPlugInCursorHelper Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.FetchAll
Try
Dim allCursor As SimplePointCursor = New SimplePointCursor(m_fullPath, Me.Fields(ClassIndex), -1, CType(FieldMap, System.Array), Nothing, Me.geometryTypeByID(ClassIndex))
setMZ(allCursor, ClassIndex)
Return CType(allCursor, IPlugInCursorHelper)
Catch ex As Exception
System.Diagnostics.Debug.WriteLine(ex.Message)
Return Nothing
End Try
End Function
Public Function FetchByEnvelope(ByVal ClassIndex As Integer, ByVal env As ESRI.ArcGIS.Geometry.IEnvelope, ByVal strictSearch As Boolean, ByVal WhereClause As String, ByVal FieldMap As Object) As ESRI.ArcGIS.Geodatabase.IPlugInCursorHelper Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.FetchByEnvelope
If Me.DatasetType = esriDatasetType.esriDTTable Then
Return Nothing
End If
'env passed in always has same spatial reference as the data
'for identify, it will check if search geometry intersect dataset bound
'but not ITable.Search(pSpatialQueryFilter, bRecycle) etc
'so here we should check if input env falls within extent
Dim boundEnv As IEnvelope = Me.Bounds
boundEnv.Project(env.SpatialReference)
If boundEnv.IsEmpty Then
Return Nothing 'or raise error?
End If
Try
Dim spatialCursor As SimplePointCursor = New SimplePointCursor(m_fullPath, Me.Fields(ClassIndex), -1, CType(FieldMap, System.Array), env, Me.geometryTypeByID(ClassIndex))
setMZ(spatialCursor, ClassIndex)
Return CType(spatialCursor, IPlugInCursorHelper)
Catch ex As Exception
System.Diagnostics.Debug.WriteLine(ex.Message)
Return Nothing
End Try
End Function
Public Function FetchByID(ByVal ClassIndex As Integer, ByVal ID As Integer, ByVal FieldMap As Object) As ESRI.ArcGIS.Geodatabase.IPlugInCursorHelper Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.FetchByID
Try
Dim idCursor As SimplePointCursor = New SimplePointCursor(m_fullPath, Me.Fields(ClassIndex), ID, CType(FieldMap, System.Array), Nothing, Me.geometryTypeByID(ClassIndex))
setMZ(idCursor, ClassIndex)
Return CType(idCursor, IPlugInCursorHelper)
Catch ex As Exception 'will catch NextRecord error if it reaches EOF without finding a record
System.Diagnostics.Debug.WriteLine(ex.Message)
Return Nothing
End Try
End Function
#End Region
Public ReadOnly Property Fields(ByVal ClassIndex As Integer) As ESRI.ArcGIS.Geodatabase.IFields Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.Fields
Get
Dim fieldEdit As IFieldEdit
Dim flds As IFields
Dim fieldsEdit As IFieldsEdit
Dim fcDesc As IObjectClassDescription
If Me.DatasetType = esriDatasetType.esriDTTable Then
fcDesc = New ObjectClassDescriptionClass()
Else
fcDesc = New FeatureClassDescriptionClass()
End If
flds = fcDesc.RequiredFields
fieldsEdit = CType(flds, IFieldsEdit)
fieldEdit = New FieldClass()
fieldEdit.Length_2 = 1
fieldEdit.Name_2 = "ColumnOne"
fieldEdit.Type_2 = esriFieldType.esriFieldTypeString
fieldsEdit.AddField(CType(fieldEdit, IField))
'HIGHLIGHT: Add extra int column
fieldEdit = New FieldClass()
fieldEdit.Name_2 = "Extra"
fieldEdit.Type_2 = esriFieldType.esriFieldTypeInteger
fieldsEdit.AddField(CType(fieldEdit, IField))
'HIGHLIGHT: Set shape field geometry definition
If Me.DatasetType <> esriDatasetType.esriDTTable Then
Dim field As IField = flds.Field(flds.FindField("Shape"))
fieldEdit = CType(field, IFieldEdit)
Dim geomDefEdit As IGeometryDefEdit = CType(field.GeometryDef, IGeometryDefEdit)
geomDefEdit.GeometryType_2 = geometryTypeByID(ClassIndex)
Dim shapeSRef As ISpatialReference = Me.spatialReference
' #Region "M & Z"
'M
If (ClassIndex >= 3 AndAlso ClassIndex <= 5) OrElse ClassIndex >= 9 Then
geomDefEdit.HasM_2 = True
shapeSRef.SetMDomain(0, 1000)
Else
geomDefEdit.HasM_2 = False
End If
'Z
If ClassIndex >= 6 Then
geomDefEdit.HasZ_2 = True
shapeSRef.SetZDomain(0, 1000)
Else
geomDefEdit.HasZ_2 = False
End If
' #End Region
geomDefEdit.SpatialReference_2 = shapeSRef
End If
Return flds
End Get
End Property
Public ReadOnly Property OIDFieldIndex(ByVal ClassIndex As Integer) As Integer Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.OIDFieldIndex
Get
Return 0
End Get
End Property
Public ReadOnly Property ShapeFieldIndex(ByVal ClassIndex As Integer) As Integer Implements ESRI.ArcGIS.Geodatabase.IPlugInDatasetHelper.ShapeFieldIndex
Get
'add table to ArcMap via add data dialog calls this method, so if it's a table
'you must return -1 or else ArcMap crashes
If Me.DatasetType = esriDatasetType.esriDTTable Then
Return -1
End If
Return 1
End Get
End Property
#End Region
#Region "internal helper methods"
Private Function geometryTypeByID(ByVal ClassIndex As Integer) As esriGeometryType
If Me.DatasetType = esriDatasetType.esriDTTable Then
Return esriGeometryType.esriGeometryNull
End If
If ClassIndex Mod 3 = 0 Then
Return esriGeometryType.esriGeometryPoint
ElseIf ClassIndex Mod 3 = 1 Then
Return esriGeometryType.esriGeometryPolyline
Else
Return esriGeometryType.esriGeometryPolygon
End If
End Function
Private ReadOnly Property spatialReference() As ISpatialReference
Get
If Me.DatasetType = esriDatasetType.esriDTTable Then
Return Nothing
End If
'singleton
Dim srefFact As ISpatialReferenceFactory2 = New SpatialReferenceEnvironmentClass()
Return srefFact.CreateProjectedCoordinateSystem(Convert.ToInt32(esriSRProjCSType.esriSRProjCS_World_Robinson)) ' WGS1984UTM_10N));
End Get
End Property
Private Sub setMZ(ByVal sptCursor As SimplePointCursor, ByVal Index As Integer)
sptCursor.HasM = ((Index >= 3 AndAlso Index < 6) OrElse Index >= 9)
sptCursor.HasZ = (Index >= 6)
End Sub
#End Region
End Class