Ryan,
Below is the code I promised. We will post this as a code community project soon but before that I wanted to get you the source. The key is that there are some certain fields that have to be in the DBF and they have some rules about them.
1. The first column needs to be prefixed with 'ID_' so in the example we use 'ID_Name' . When you add the data to the DBF you must add the data sorted on this field from A-Z.
2. For data int he DBF you want returned profix it with 'DT_' which stands for detail. If a column does not have 'DT_' in front of it then it will not return in the search results.
3. There are 6 spatial fields we need at the end of the file. They are BB_CX (Bounding Box Center X), BB_CY (Bounding Box Center X), BB_ULX (Bounding Box Upper Left Y), BB_ULY (Bounding Box Upper Left Y), BB_LRX (Bounding Box Lower Right X), BB_LRY (Bounding Box Lower Right Y). These fields need to be in integer format. You do this by multiplying the decimal degree value by 1,000,000 (See code example)
4. We use the above bounding box fields to zoom into the item found when we complete the search.
Let me know if you have any questions
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.MapSuiteGeocoder;
namespace BuildIndexFileFromShapeFile
{
public partial class Sample : Form
{
// We use this to convert the decimal degree value, which is a double, to a integer to save 4 bytes
private const int coordinatesMultiplier = 1000000;
public Sample()
{
InitializeComponent();
}
private void btnBuildIndex_Click(object sender, EventArgs e)
{
// Here we create an empty DbfMatchPlugin with all of the columns
DbfMatchingPlugin dbfMatchingPlugin = CreateEmptyDbfMatchingPlugin();
// Here we load the shape file data, sort it and get it ready to add
List<string> dataSource = PrepareData();
// Here we add the sorted date to the DBFMatchPlugin
PopulateDbfMatchPlugin(dataSource, dbfMatchingPlugin);
MessageBox.Show("Build Index Completed", "Build Index File", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
}
private DbfMatchingPlugin CreateEmptyDbfMatchingPlugin()
{
// Here we create the column collection
Collection<DbfMatchingPluginColumn> columns = new Collection<DbfMatchingPluginColumn>();
// Note that the first field needs to have an 'ID_' prefix. This also needs to be unique and sorted A-Z
columns.Add(new DbfMatchingPluginColumn("ID_Name", ThinkGeo.MapSuite.MapSuiteGeocoder.DbfMatchingPluginColumnType.String, 50));
// The columns prefixed with 'DT_' are just detail columns. They will be returned in the result but we
// ignore them from a program perspective
columns.Add(new DbfMatchingPluginColumn("DT_FIPS", DbfMatchingPluginColumnType.String, 5));
columns.Add(new DbfMatchingPluginColumn("DT_Pop", DbfMatchingPluginColumnType.Long, 4));
columns.Add(new DbfMatchingPluginColumn("DT_CuType", DbfMatchingPluginColumnType.String, 20));
columns.Add(new DbfMatchingPluginColumn("DT_CuCode", DbfMatchingPluginColumnType.String, 10));
columns.Add(new DbfMatchingPluginColumn("DT_Color", DbfMatchingPluginColumnType.String, 2));
// The 'BB_CX' & 'BB_CY' stands for the bounding box center point X and Y
// The 'BB_ULX' stand for the following.. Upper Left X, Upperl Left Y, Lower Right X and Lower Right Y
// They are used by the geocoder to zoom into the selection once it is found
columns.Add(new DbfMatchingPluginColumn("BB_CX", DbfMatchingPluginColumnType.Long, 4));
columns.Add(new DbfMatchingPluginColumn("BB_CY", DbfMatchingPluginColumnType.Long, 4));
columns.Add(new DbfMatchingPluginColumn("BB_ULX", DbfMatchingPluginColumnType.Long, 4));
columns.Add(new DbfMatchingPluginColumn("BB_ULY", DbfMatchingPluginColumnType.Long, 4));
columns.Add(new DbfMatchingPluginColumn("BB_LRX", DbfMatchingPluginColumnType.Long, 4));
columns.Add(new DbfMatchingPluginColumn("BB_LRY", DbfMatchingPluginColumnType.Long, 4));
// This method creates the DBF based on the columns defines above
DbfMatchingPlugin.CreateDbf(@"..\..\Data\Countries-PluginFormat.dbf", columns);
// Here we just open the plugin we just created and pass it back out of the method
DbfMatchingPlugin dbfMathingPlugin = new DbfMatchingPlugin(@"..\..\Data\Countries-PluginFormat.dbf", DbfMatchingPluginReadWriteMode.ReadWrite);
dbfMathingPlugin.Open();
return dbfMathingPlugin;
}
private List<string> PrepareData()
{
List<string> dataSource = new List<string>();
// Build the index file incase it is not built
ShapeFileFeatureLayer.BuildIndexFile(@"..\..\Data\cntry02.shp", BuildIndexMode.DoNotRebuild);
// Open the shape file we will use to construct the match plugin
ShapeFileFeatureLayer shapeFile = new ShapeFileFeatureLayer(@"..\..\Data\cntry02.shp");
shapeFile.Open();
// Get all the features from the shapefile with all the columns
Collection<Feature> features = shapeFile.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns);
// Loop through each feature and get the bounding box and add it to the datasource
foreach (Feature feature in features)
{
// Calculate the boundingbox and center point then converts the doubles to int for storage in the DbfMatchPlugin
RectangleShape boundingBox = feature.GetBoundingBox();
// Center Point
int centerX = Convert.ToInt32(Math.Round(boundingBox.GetCenterPoint().X, 6) * coordinatesMultiplier);
int centerY = Convert.ToInt32(Math.Round(boundingBox.GetCenterPoint().Y, 6) * coordinatesMultiplier);
// Bounding Box
int ulPointX = Convert.ToInt32(Math.Round(boundingBox.UpperLeftPoint.X, 6) * coordinatesMultiplier);
int ulPointY = Convert.ToInt32(Math.Round(boundingBox.UpperLeftPoint.Y, 6) * coordinatesMultiplier);
int lrPointX = Convert.ToInt32(Math.Round(boundingBox.LowerRightPoint.X, 6) * coordinatesMultiplier);
int lrPointY = Convert.ToInt32(Math.Round(boundingBox.LowerRightPoint.Y, 6) * coordinatesMultiplier);
// Read this row into a string to be added to the data source. We also add the bounding box
// to the end of the row
string sourceStr = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}|{10}|{11}", feature.ColumnValues["CNTRY_NAME"], feature.ColumnValues["FIPS_CNTRY"], feature.ColumnValues["POP_CNTRY"], feature.ColumnValues["CURR_TYPE"], feature.ColumnValues["CURR_CODE"], feature.ColumnValues["COLOR_MAP"], centerX, centerY, ulPointX, ulPointY, lrPointX, lrPointY);
// Add the data to the datasource
dataSource.Add(sourceStr);
}
// Sort the data so that the country name is sorted from A-Z
dataSource.Sort(delegate(string lineA, string lineB)
{ return string.Compare(lineA.Split('|')[0], lineB.Split('|')[0], StringComparison.OrdinalIgnoreCase); });
return dataSource;
}
private void PopulateDbfMatchPlugin(List<string> dataSource, DbfMatchingPlugin dbfMatchingPlugin)
{
// Loop through all the data in the data source, which should already be sorted, and add it to
// the DbfMatchPlugin
foreach (string line in dataSource)
{
// Cast all of the data to the proper types
string[] parts = line.Split('|');
string cntryName = parts[0];
string fips = parts[1];
int pop = int.Parse(parts[2]);
string currType = parts[3];
string currCode = parts[4];
string colorMap = parts[5];
int centerX = int.Parse(parts[6]);
int centerY = int.Parse(parts[7]);
int ulPointX = int.Parse(parts[8]);
int ulPointY = int.Parse(parts[9]);
int lrPointX = int.Parse(parts[10]);
int lrPointY = int.Parse(parts[11]);
// Add the record to the DbfMatchPlugin
dbfMatchingPlugin.AddRecord(new object[] { cntryName, fips, pop, currType, currCode, colorMap, centerX, centerY, ulPointX, ulPointY, lrPointX, lrPointY });
}
dbfMatchingPlugin.Close();
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
David