About the Create a custom raster type from the ground up for DMCII data Sample
[C#]
DMCIIRasterType.cs
using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.DataSourcesRaster;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Carto;
/*
*
* This sample shows how to implement a Custom Raster Type to provide support for DMCII data.
* Also provided is an optional test application to create a Geodatabase and a mosaic dataset
* and add data using the custom type.
* The main interface to be implemented is the IRasterBuilder interface along with
* secondary interfaces such as IRasterBuilderInit (which provides access to the parent MD),
* IPersistvariant (which implements persistence), IRasterBuilderInit2 and IRasterBuilder2
* (new interfaces added at 10.1).
* A IRasterFactory implementation also needs to be created in order for the Raster type to
* show up in the list of Raster Types in the Add Rasters GP Tool. The factory is responsible
* for creating the raster type object and setting some properties on it. It also enables the
* use of the Raster Product.
*
*/
namespace SampleRasterType
{
[Guid("5DEF8E3C-51E9-49af-A3BE-EF8C68A4BBBE")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("SampleRasterType.CustomRasterTypeFactory")]
[ComVisible(true)]
public class DMCIIRasterTypeFactory : IRasterTypeFactory
{
#region Private Members
IStringArray myRasterTypeNames; // List of Raster Types that the factory can create.
UID myUID; // UID for the DMCII Raster Type.
#endregion
#region IRasterTypeFactory Members
public DMCIIRasterTypeFactory()
{
string rasterTypeName = "DMCII Raster Type";
myRasterTypeNames = new StrArrayClass();
myRasterTypeNames.Add(rasterTypeName);
myUID = new UIDClass();
myUID.Value = "{5DEF8E3C-51E9-49af-A3BE-EF8C68A4BBBE}";
}
public UID CLSID
{
get { return myUID; }
}
/// <summary>
/// Create a Raster Type object given the name of the raster type (usually
/// the same name as the one in the UI list of raster types).
/// </summary>
/// <param name="RasterTypeName">Name of the Raster Type object to create.</param>
/// <returns>The Raster type object.</returns>
public IRasterType CreateRasterType(string RasterTypeName)
{
// Create a new RasterType object and its corresponding name object.
IRasterType theRasterType = new RasterTypeClass();
IRasterTypeName theRasterTypeName = new RasterTypeNameClass();
theRasterTypeName.Name = RasterTypeName;
theRasterType.FullName = (IName)theRasterTypeName;
// Set the properties for the raster type object. These are shown in the
// 'General' tab of the raster type properties page.
((IRasterTypeProperties)theRasterType).Name = "DMCII Raster Type";
((IRasterTypeProperties)theRasterType).Description = "Raster Type for DMCII data.";
((IRasterTypeProperties)theRasterType).DataSourceFilter = "*.dim";
((IRasterTypeProperties)theRasterType).SupportsOrthorectification = true;
// Create the Custom Raster Builder object
IRasterBuilder customRasterBuilder = new DMCIIRasterBuilder();
// Set the Raster Builder of theRasterType to the above created builder.
theRasterType.RasterBuilder = customRasterBuilder;
// Enable the use of the Raster Type as a Raster Product.
((IRasterTypeProperties2)theRasterType).IsSensorRasterType = true;
#region Set Product Templates
// Create a new array of templates if needed.
if (theRasterType.ItemTemplates == null)
theRasterType.ItemTemplates = new ItemTemplateArrayClass();
// Add a 'Raw' template.
IItemTemplate nullTemplate = new ItemTemplateClass();
nullTemplate.Enabled = false;
nullTemplate.Name = "Raw";
((IItemTemplate2)nullTemplate).IsSensorTemplate = true;
((IItemTemplate2)nullTemplate).SupportsEnhancement = false;
theRasterType.ItemTemplates.Add(nullTemplate);
// Add a 'Stretch' template. This is the default template.
IItemTemplate strTemplate = new ItemTemplateClass();
strTemplate.Enabled = true;
strTemplate.Name = "Stretch";
IRasterFunction stretchFunction = new StretchFunctionClass();
IStretchFunctionArguments stretchFunctionArgs = new StretchFunctionArgumentsClass();
stretchFunctionArgs.StretchType = esriRasterStretchType.esriRasterStretchMinimumMaximum;
IRasterFunctionVariable rasterVar = new RasterFunctionVariableClass();
rasterVar.IsDataset = true;
rasterVar.Name = "MS";
rasterVar.Aliases = new StrArrayClass();
rasterVar.Aliases.Add("MS");
rasterVar.Description = "Variable for input raster";
stretchFunctionArgs.Raster = rasterVar;
IRasterFunctionTemplate stretchFunctionTemplate = new RasterFunctionTemplateClass();
stretchFunctionTemplate.Function = stretchFunction;
stretchFunctionTemplate.Arguments = stretchFunctionArgs;
strTemplate.RasterFunctionTemplate = stretchFunctionTemplate;
((IItemTemplate2)strTemplate).IsSensorTemplate = true;
((IItemTemplate2)strTemplate).SupportsEnhancement = true;
theRasterType.ItemTemplates.Add(strTemplate);
#endregion
#region Set Product Types
// Add Product types (called URI filters in the code).
if (((IRasterTypeProperties)theRasterType).SupportedURIFilters == null)
((IRasterTypeProperties)theRasterType).SupportedURIFilters = new ArrayClass();
// Create and setup URI Filters
IItemURIFilter allFilter = new URIProductNameFilterClass();
allFilter.Name = "All";
allFilter.SupportsOrthorectification = true;
allFilter.SupportedTemplateNames = new StrArrayClass();
allFilter.SupportedTemplateNames.Add("Raw");
allFilter.SupportedTemplateNames.Add("Stretch");
IStringArray allProductNames = new StrArrayClass();
allProductNames.Add("L1T");
allProductNames.Add("L1R");
((IURIProductNameFilter)allFilter).ProductNames = allProductNames;
// The L1T filter does not support orthorectification.
IItemURIFilter l1tFilter = new URIProductNameFilterClass();
l1tFilter.Name = "L1T";
l1tFilter.SupportsOrthorectification = false;
l1tFilter.SupportedTemplateNames = new StrArrayClass();
l1tFilter.SupportedTemplateNames.Add("Raw");
l1tFilter.SupportedTemplateNames.Add("Stretch");
IStringArray l1tProductNames = new StrArrayClass();
l1tProductNames.Add("L1T");
((IURIProductNameFilter)l1tFilter).ProductNames = l1tProductNames;
IItemURIFilter l1rFilter = new URIProductNameFilterClass();
l1rFilter.Name = "L1R";
l1rFilter.SupportsOrthorectification = true;
l1rFilter.SupportedTemplateNames = new StrArrayClass();
l1rFilter.SupportedTemplateNames.Add("Raw");
l1rFilter.SupportedTemplateNames.Add("Stretch");
IStringArray l1rProductNames = new StrArrayClass();
l1rProductNames.Add("L1R");
((IURIProductNameFilter)l1rFilter).ProductNames = l1rProductNames;
// Add them to the supported uri filters list
((IRasterTypeProperties)theRasterType).SupportedURIFilters.Add(allFilter);
((IRasterTypeProperties)theRasterType).SupportedURIFilters.Add(l1tFilter);
((IRasterTypeProperties)theRasterType).SupportedURIFilters.Add(l1rFilter);
// Set 'All' as default
theRasterType.URIFilter = allFilter;
#endregion
return theRasterType;
}
/// <summary>
/// Name of the Raster Type Factory
/// </summary>
public string Name
{
get { return "Custom Raster Type Factory"; }
}
/// <summary>
/// Names of the Raster Types supported by the factory.
/// </summary>
public IStringArray RasterTypeNames
{
get { return myRasterTypeNames; }
}
#endregion
#region COM Registration Function(s)
[ComRegisterFunction()]
static void Reg(string regKey)
{
ESRI.ArcGIS.ADF.CATIDs.RasterTypeFactory.Register(regKey);
}
[ComUnregisterFunction()]
static void Unreg(string regKey)
{
ESRI.ArcGIS.ADF.CATIDs.RasterTypeFactory.Unregister(regKey);
}
#endregion
}
[Guid("316725CB-35F2-4159-BEBB-A1445ECE9CF1")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("SampleRasterType.CustomRasterType")]
[ComVisible(true)]
public class DMCIIRasterBuilder : IRasterBuilder, IRasterBuilderInit, IPersistVariant,
IRasterBuilder2, IRasterBuilderInit2
{
#region Private Members
// The Mosaic Dataset currently using the Raster Type.
IMosaicDataset myMosaicDataset;
// The default spatial reference to apply to added data (if no spatial reference exists).
ISpatialReference myDefaultSpatialReference;
// The Raster Type Operation object (usually a Raster Type object).
IRasterTypeOperation myRasterTypeOperation;
// The Raster Type Properties.
IPropertySet myRasterTypeProperties;
// Array to fill with ItemURI's.
IItemURIArray myURIArray;
// GeoTransform helper object.
IGeoTransformationHelper myGeoTransformationHelper;
// Flags to specify whether the Raster Type can merge items and
bool myCanMergeItems;
// if it has merged item.
bool myMergeItems;
// Mapping from field names to names or properties in the item propertyset.
IPropertySet myAuxiliaryFieldAlias;
// Fields to add to the Mosaic Dataset when items are added through this Raster Type.
IFields myAuxiliaryFields;
ITrackCancel myTrackCancel;
UID myUID; // UID for the Custom Builder.
// The current dimap file being processed.
string myCurrentDimFile;
#endregion
public DMCIIRasterBuilder()
{
myMosaicDataset = null;
myDefaultSpatialReference = null;
myRasterTypeOperation = null;
myRasterTypeProperties = null;
myTrackCancel = null;
myURIArray = null;
myGeoTransformationHelper = null;
myCanMergeItems = false;
myMergeItems = false;
myAuxiliaryFieldAlias = null;
myAuxiliaryFields = null;
myUID = new UIDClass();
myUID.Value = "{316725CB-35F2-4159-BEBB-A1445ECE9CF1}";
}
#region IRasterBuilder Members
/// <summary>
/// This defines a mapping from field names in the attribute table of the mosaic to
/// properties in the property set associated with the dataset, incase a user wants
/// specify fields which are different from the property in the dataset.
/// e.g. The field CloudCover may map to a property called C_C in the dataset built
/// by the builder.
/// </summary>
public IPropertySet AuxiliaryFieldAlias
{
get
{
return myAuxiliaryFieldAlias;
}
set
{
myAuxiliaryFieldAlias = value;
}
}
/// <summary>
/// Specify fields if necessary to be added to the Mosaic Dataset when
/// items are added throug hthis Raster Type.
/// </summary>
public IFields AuxiliaryFields
{
get
{
if (myAuxiliaryFields == null)
{
myAuxiliaryFields = new FieldsClass();
AddFields(myAuxiliaryFields);
}
return myAuxiliaryFields;
}
set
{
myAuxiliaryFields = value;
}
}
/// <summary>
/// Get a crawler recommended by the Raster Type based on the data srouce properties provided.
/// </summary>
/// <param name="pDataSourceProperties">Data source properties.</param>
/// <returns>Data source crawler recommended by the raster type.</returns>
public IDataSourceCrawler GetRecommendedCrawler(IPropertySet pDataSourceProperties)
{
try
{
// This is usually a file crawler because it can crawl directories as well, unless
// special types of data needs to be crawled.
IDataSourceCrawler myCrawler = new FileCrawlerClass();
((IFileCrawler)myCrawler).Path = Convert.ToString(pDataSourceProperties.GetProperty("Source"));
((IFileCrawler)myCrawler).Recurse = Convert.ToBoolean(pDataSourceProperties.GetProperty("Recurse"));
myCrawler.Filter = Convert.ToString(pDataSourceProperties.GetProperty("Filter"));
if (myCrawler.Filter == null || myCrawler.Filter == "")
myCrawler.Filter = "*.dim";
return myCrawler;
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Prepare the Raster Type for generating item Unique Resource Identifier (URI)
/// </summary>
/// <param name="pCrawler">Crawler to use to generate the item URI's</param>
public void BeginConstruction(IDataSourceCrawler pCrawler)
{
myURIArray = new ItemURIArrayClass();
}
/// <summary>
/// Construct a Unique Resource Identifier (URI)
/// for each crawler item
/// </summary>
/// <param name="crawlerItem">Crawled Item from which the URI is generated</param>
public void ConstructURIs(object crawlerItem)
{
myCurrentDimFile = (string)crawlerItem;
}
/// <summary>
/// Finish construction of the URI's
/// </summary>
/// <returns>Array containing finised URI's</returns>
public IItemURIArray EndConstruction()
{
return myURIArray;
}
/// <summary>
/// Generate the next URI.
/// </summary>
/// <returns>The URI generated.</returns>
public IItemURI GetNextURI()
{
IItemURI newURI = null;
try
{
// Check to see if the item cralwed is a .dim file.
if (myCurrentDimFile != "" && myCurrentDimFile != null && myCurrentDimFile.EndsWith(".dim"))
{
// Create a new Dimap Parser obect and item uri.
DiMapParser myDimParser = new DiMapParser(myCurrentDimFile);
newURI = new ItemURIClass();
// Set the display name, Group, Product Name, Tag and Key.
newURI.DisplayName = System.IO.Path.GetFileName(myCurrentDimFile);
newURI.Group = System.IO.Path.GetFileNameWithoutExtension(myCurrentDimFile);
newURI.Key = myCurrentDimFile;
newURI.ProductName = myDimParser.ProductType;
newURI.Tag = "MS";
// Set the timestamp of the dimfile as source time stamp. This helps
// with synchronization later.
IRasterTypeEnvironment myEnv = new RasterTypeEnvironmentClass();
DateTime dimTS = myEnv.GetTimeStamp(myCurrentDimFile);
newURI.SourceTimeStamp = dimTS;
myDimParser = null;
myCurrentDimFile = "";
myURIArray.Add(newURI);
}
}
catch (Exception)
{
throw;
}
return newURI;
}
/// <summary>
/// Build the Builder Item which includes the function raster dataset and its footprint
/// given the ItemURI.
/// </summary>
/// <param name="pItemURI">ItemURi to use to build the Builder Item.</param>
/// <returns>The builder item.</returns>
public IBuilderItem Build(IItemURI pItemURI)
{
try
{
// Create a new parser object and builder item.
DiMapParser myDimParser = new DiMapParser(pItemURI.Key);
IBuilderItem currItem = new BuilderItemClass();
// Set Category and URI
currItem.Category = esriRasterCatalogItemCategory.esriRasterCatalogItemCategoryPrimary;
currItem.URI = pItemURI;
// Set FunctionRasterDataset
IFunctionRasterDataset inputFrd = GetFRD(myDimParser, pItemURI);
currItem.Dataset = inputFrd;
// Set band information for the function dataset including names, wavelengths and stats if available.
SetBandProperties((IDataset)inputFrd, myDimParser);
// Set Footprint
IGeoDataset geoDset = (IGeoDataset)inputFrd;
// Set it to the current raster extent first. If the raster has no
// spatial reference, the extents will be in pixel space.
currItem.Footprint = (IGeometry)geoDset.Extent;
// The get the footprint from the dim file is it exists.
currItem.Footprint = GetFootprint(myDimParser);
// Set Properties. These properties are used to fill the Auxiliary Fields
// defined earlier and also key properties if the names are correct.
IPropertySet propSet = currItem.Dataset.Properties;
if (null == propSet)
propSet = new PropertySetClass();
double sunAzimuth = Convert.ToDouble(myDimParser.SunAzimuth);
double sunElevation = Convert.ToDouble(myDimParser.SunElevation);
double sensorAzimuth = Convert.ToDouble(myDimParser.SensorAzimuth);
double sensorElevation = 180 - Convert.ToDouble(myDimParser.IncidenceAngle);
string acqDate = myDimParser.AcquisitionDate;
string acqTime = myDimParser.AcquisitionTime;
// Create a time object from the provided date and time.
ITime acqDateTimeObj = new TimeClass();
acqDateTimeObj.SetFromTimeString(esriTimeStringFormat.esriTSFYearThruSubSecondWithDash,
acqDate + " " + acqTime);
// and obtain a DateTime object to set as value of the property. This ensures the
// field displays the value correctly.
DateTime acqDateTimeFieldVal = acqDateTimeObj.QueryOleTime();
propSet.SetProperty("AcquisitionDate", acqDateTimeFieldVal);
propSet.SetProperty("SensorName", myDimParser.MetadataProfile);
propSet.SetProperty("SunAzimuth", sunAzimuth);
propSet.SetProperty("SunElevation", sunElevation);
propSet.SetProperty("SatAzimuth", sensorAzimuth);
propSet.SetProperty("SatElevation", sensorElevation);
currItem.Dataset.Properties = propSet;
return currItem;
}
catch (Exception exc)
{
throw exc;
}
}
/// <summary>
/// Flag to specify whether the Raster Builder can build items in place.
/// </summary>
public bool CanBuildInPlace
{
get { return false; }
}
/// <summary>
/// Check if the item provided is "stale" or not valid
/// </summary>
/// <param name="pItemURI">URI for the item to be checked</param>
/// <returns>Flag to specify whether the item is stale or not.</returns>
public bool IsStale(IItemURI pItemURI)
{
try
{
IRasterTypeEnvironment myEnv = new RasterTypeEnvironmentClass();
DateTime currDimTS = myEnv.GetTimeStamp(pItemURI.Key);
return pItemURI.SourceTimeStamp != currDimTS;
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// Properties associated with the Raster Type
/// </summary>
public IPropertySet Properties
{
get
{
if (myRasterTypeProperties == null)
myRasterTypeProperties = new PropertySetClass();
return myRasterTypeProperties;
}
set
{
myRasterTypeProperties = value;
}
}
/// <summary>
/// Sets band properties on a given dataset including stats, band names and wavelengths.
/// </summary>
/// <param name="dataset">The dataset to set properties on.</param>
/// <param name="dimParser">Dimap parser to read properties from.</param>
private void SetBandProperties(IDataset dataset, DiMapParser dimParser)
{
try
{
// Set band band props.
IRasterKeyProperties rasterKeyProps = (IRasterKeyProperties)dataset;
IRasterBandCollection rasterBandColl = (IRasterBandCollection)dataset;
int imageNumBands = ((IFunctionRasterDataset)dataset).RasterInfo.BandCount;
int dinNumBands = dimParser.NumBands;
int[] bandIndexes = new int[dinNumBands];
IStringArray bandNames = new StrArrayClass();
for (int i = 0; i < dinNumBands; ++i)
{
// Get band index for the first band.
bandIndexes[i] = Convert.ToInt16(dimParser.GetBandIndex(i));
// Validate band index.
if (bandIndexes[i] > 0 && bandIndexes[i] <= imageNumBands)
{
// Get Band Name for the index.
bandNames.Add(dimParser.GetBandDesc(bandIndexes[i]));
// Get Band stats for the index.
IRasterStatistics bandStats = new RasterStatisticsClass();
bandStats.Minimum = Convert.ToDouble(dimParser.GetBandStatMin(bandIndexes[i]));
bandStats.Maximum = Convert.ToDouble(dimParser.GetBandStatMax(bandIndexes[i]));
bandStats.Mean = Convert.ToDouble(dimParser.GetBandStatMean(bandIndexes[i]));
bandStats.StandardDeviation = Convert.ToDouble(dimParser.GetBandStatStdDev(bandIndexes[i]));
// Set stats on the dataset.
((IRasterBandEdit2)rasterBandColl.Item(bandIndexes[i] - 1)).AlterStatistics(bandStats);
// Set Band Name and wavelengths according to the name.
rasterKeyProps.SetBandProperty("BandName", (bandIndexes[i] - 1), bandNames.get_Element(i));
SetBandWavelengths(dataset, (bandIndexes[i] - 1));
// Refresh dataset so changes are saved.
((IRasterDataset3)dataset).Refresh();
}
}
}
catch (Exception exc)
{
string error = exc.Message;
}
}
/// <summary>
/// Set the wavelengths corresponding to the band name.
/// </summary>
private void SetBandWavelengths(IDataset dataset, int bandIndex)
{
IRasterKeyProperties rasterKeyProps = (IRasterKeyProperties)dataset;
IRasterBandCollection rasterBandColl = (IRasterBandCollection)dataset;
string bandName = (string)rasterKeyProps.GetBandProperty("BandName", bandIndex);
// Set wavelengths for the bands
switch (bandName.ToLower())
{
case "red":
{
rasterKeyProps.SetBandProperty("WavelengthMin", bandIndex, 630);
rasterKeyProps.SetBandProperty("WavelengthMax", bandIndex, 690);
}
break;
case "green":
{
rasterKeyProps.SetBandProperty("WavelengthMin", bandIndex, 520);
rasterKeyProps.SetBandProperty("WavelengthMax", bandIndex, 600);
}
break;
case "nir":
case "nearinfrared":
{
rasterKeyProps.SetBandProperty("WavelengthMin", bandIndex, 770);
rasterKeyProps.SetBandProperty("WavelengthMax", bandIndex, 900);
}
break;
}
}
//private IGeometry GetFootprint(DiMapParser dimParser)
//{
// IGeometry currFootprint = null;
// dimParser.ResetVertexCount();
// string xs = "";
// string ys = "";
// string rows = "";
// string cols = "";
// double minX = 10000000000.0;
// double maxX = -1000000000.00;
// double minY = 1000000000.00;
// double maxY = -1000000000.00;
// double minRow = 1000000000.00;
// double maxRow = -1000000000.0;
// double minCol = 1000000000.00;
// double maxCol = -1000000000.0;
// double x = 0.0;
// double y = 0.0;
// double row = 0.0;
// double col = 0.0;
// while (dimParser.GetNextVertex(out xs, out ys, out rows, out cols))
// {
// x = Convert.ToDouble(xs);
// y = Convert.ToDouble(ys);
// row = Convert.ToDouble(rows);
// col = Convert.ToDouble(cols);
// if (x < minX)
// minX = x;
// if (x > maxX)
// maxX = x;
// if (y < minY)
// minY = y;
// if (y > maxY)
// maxY = y;
// if (row < minRow)
// minRow = row;
// if (row > maxRow)
// maxRow = row;
// if (col < minCol)
// minCol = col;
// if (col > maxCol)
// maxCol = col;
// x = 0.0;
// y = 0.0;
// row = 0.0;
// col = 0.0;
// xs = "";
// ys = "";
// rows = "";
// cols = "";
// }
// x = Convert.ToDouble(xs);
// y = Convert.ToDouble(ys);
// row = Convert.ToDouble(rows);
// col = Convert.ToDouble(cols);
// if (x < minX)
// minX = x;
// if (x > maxX)
// maxX = x;
// if (y < minY)
// minY = y;
// if (y > maxY)
// maxY = y;
// if (row < minRow)
// minRow = row;
// if (row > maxRow)
// maxRow = row;
// if (col < minCol)
// minCol = col;
// if (col > maxCol)
// maxCol = col;
// currFootprint = new PolygonClass();
// IPointCollection currPointColl = (IPointCollection)currFootprint;
// IEnvelope rectEnvelope = new EnvelopeClass();
// rectEnvelope.PutCoords(minX, minY, maxX, maxY);
// ISegmentCollection segmentCollection = (ISegmentCollection)currFootprint;
// segmentCollection.SetRectangle(rectEnvelope);
// // Get Srs
// int epsgcode = Convert.ToInt32((dimParser.SrsCode.Split(':'))[1]);
// ISpatialReferenceFactory3 srsfactory = new SpatialReferenceEnvironmentClass();
// ISpatialReference dimSrs = srsfactory.CreateSpatialReference(epsgcode);
// ISpatialReferenceResolution srsRes = (ISpatialReferenceResolution)dimSrs;
// srsRes.ConstructFromHorizon();
// srsRes.SetDefaultXYResolution();
// ((ISpatialReferenceTolerance)dimSrs).SetDefaultXYTolerance();
// currFootprint.SpatialReference = dimSrs;
// #region Commented
// //IEnvelope extent = new EnvelopeClass();
// //extent.XMin = geoDset.Extent.XMin;
// //extent.XMax = geoDset.Extent.XMax;
// //extent.YMin = geoDset.Extent.YMin;
// //extent.YMax = geoDset.Extent.YMax;
// //extent.SpatialReference = geoDset.SpatialReference;
// //extent.Width = inputFrd.RasterInfo.Extent.Width;
// //extent.Height = inputFrd.RasterInfo.Extent.Height;
// //currItem.Footprint = (IGeometry)extent;
// //myDimParser.ResetVertexCount();
// //string x = "";
// //string y = "";
// //string row = "";
// //string col = "";
// //IGeometry currFootprint = new PolygonClass();
// //IPointCollection currPointColl = (IPointCollection)currFootprint;
// // Creating a polygon!!!
// ////Build a polygon from a sequence of points.
// ////Add arrays of points to a geometry using the IGeometryBridge2 interface on the
// ////GeometryEnvironment singleton object.
// //IGeometryBridge2 geometryBridge2 = new GeometryEnvironmentClass();
// //IPointCollection4 pointCollection4 = new PolygonClass();
// ////TODO:
// ////pointCollection4.SpatialReference = 'Define the spatial reference of the new polygon.
// //WKSPoint[] aWKSPointBuffer = null;
// //long cPoints = 4; //The number of points in the first part.
// //aWKSPointBuffer = new WKSPoint[System.Convert.ToInt32(cPoints - 1) + 1];
// ////TODO:
// ////aWKSPointBuffer = 'Read cPoints into the point buffer.
// //geometryBridge2.SetWKSPoints(pointCollection4, ref aWKSPointBuffer);
// //myDimParser.GetNextVertex(out x, out y, out col, out row);
// //IPoint currPoint1 = new PointClass();
// //currPoint1.X = Convert.ToDouble(x);
// //currPoint1.Y = Convert.ToDouble(y);
// //myDimParser.GetNextVertex(out x, out y, out col, out row);
// //IPoint currPoint2 = new PointClass();
// //currPoint1.X = Convert.ToDouble(x);
// //currPoint1.Y = Convert.ToDouble(y);
// //myDimParser.GetNextVertex(out x, out y, out col, out row);
// //IPoint currPoint3 = new PointClass();
// //currPoint1.X = Convert.ToDouble(x);
// //currPoint1.Y = Convert.ToDouble(y);
// //myDimParser.GetNextVertex(out x, out y, out col, out row);
// //IPoint currPoint4 = new PointClass();
// //currPoint1.X = Convert.ToDouble(x);
// //currPoint1.Y = Convert.ToDouble(y);
// //object refPoint1 = (object)currPoint1;
// //object refPoint2 = (object)currPoint2;
// //object refPoint3 = (object)currPoint3;
// //object refPoint4 = (object)currPoint4;
// //currPointColl.AddPoint(currPoint1, ref refPoint4, ref refPoint2);
// //currPointColl.AddPoint(currPoint2, ref refPoint1, ref refPoint3);
// //currPointColl.AddPoint(currPoint3, ref refPoint2, ref refPoint4);
// //currPointColl.AddPoint(currPoint4, ref refPoint3, ref refPoint1);
// //((IPolygon)currFootprint).Close();
// //currFootprint.SpatialReference = dimSrs;
// #endregion
// return currFootprint;
//}
/// <summary>
/// Get the footprint from the dimap file if it exists.
/// </summary>
/// <param name="dimParser">Dimap file parser.</param>
/// <returns>Footprint geomtry.</returns>
private IGeometry GetFootprint(DiMapParser dimParser)
{
IGeometry currFootprint = null;
dimParser.ResetVertexCount();
string xs = "";
string ys = "";
double minX = 10000000000.0;
double maxX = -1000000000.00;
double minY = 1000000000.00;
double maxY = -1000000000.00;
double x = 0.0;
double y = 0.0;
string units = dimParser.ProductType;
if (units.ToLower() == "L1T".ToLower())
units = "M";
else if (units.ToLower() == "L1R".ToLower())
units = "Deg";
// Get vertices from the dimap file and figure out the min,max.
while (dimParser.GetNextVertex2(out xs, out ys, units))
{
x = Convert.ToDouble(xs);
y = Convert.ToDouble(ys);
if (x < minX)
minX = x;
if (x > maxX)
maxX = x;
if (y < minY)
minY = y;
if (y > maxY)
maxY = y;
x = 0.0;
y = 0.0;
xs = "";
ys = "";
}
x = Convert.ToDouble(xs);
y = Convert.ToDouble(ys);
if (x < minX)
minX = x;
if (x > maxX)
maxX = x;
if (y < minY)
minY = y;
if (y > maxY)
maxY = y;
// create a new polygon and fill it using the vertices calculated.
currFootprint = new PolygonClass();
IPointCollection currPointColl = (IPointCollection)currFootprint;
IEnvelope rectEnvelope = new EnvelopeClass();
rectEnvelope.PutCoords(minX, minY, maxX, maxY);
ISegmentCollection segmentCollection = (ISegmentCollection)currFootprint;
segmentCollection.SetRectangle(rectEnvelope);
// Get Srs from the dim file and set it on the footprint.
int epsgcode = Convert.ToInt32((dimParser.SrsCode.Split(':'))[1]);
ISpatialReferenceFactory3 srsfactory = new SpatialReferenceEnvironmentClass();
ISpatialReference dimSrs = srsfactory.CreateSpatialReference(epsgcode);
ISpatialReferenceResolution srsRes = (ISpatialReferenceResolution)dimSrs;
srsRes.ConstructFromHorizon();
srsRes.SetDefaultXYResolution();
((ISpatialReferenceTolerance)dimSrs).SetDefaultXYTolerance();
currFootprint.SpatialReference = dimSrs;
return currFootprint;
}
/// <summary>
/// Create the function raster dataset from the source images.
/// </summary>
/// <param name="dimPar">Parser for the dimap file.</param>
/// <param name="pItemURI">ItemURi to use.</param>
/// <returns>Function raster dataset created.</returns>
private IFunctionRasterDataset GetFRD(DiMapParser dimPar, IItemURI pItemURI)
{
IFunctionRasterDataset opFrd = null;
try
{
Type factoryType = Type.GetTypeFromProgID("esriDataSourcesRaster.RasterWorkspaceFactory");
IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
IWorkspace workspace = workspaceFactory.OpenFromFile(System.IO.Path.GetDirectoryName(pItemURI.Key), 0);
IRasterWorkspace rasterWorkspace = (IRasterWorkspace)workspace;
// Open the tif file associated with the .dim file as a raster dataset.
string imagePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(pItemURI.Key),
pItemURI.Group + ".tif");
string rpcPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(pItemURI.Key),
pItemURI.Group + ".rpc");
IRasterDataset inputRasterDataset = null;
if (File.Exists(imagePath))
inputRasterDataset = rasterWorkspace.OpenRasterDataset(pItemURI.Group + ".tif");
else
return null;
IFunctionRasterDataset intermedFrd = null;
// If the file opes successfully, add a RasterInfo function on top.
if (inputRasterDataset != null)
{
// Create an Identity function dataset to get the raster info.
IRasterFunction identityFunction = new IdentityFunctionClass();
IFunctionRasterDataset idFrd = new FunctionRasterDatasetClass();
idFrd.Init(identityFunction, inputRasterDataset);
// Create a raster info function dataset.
IRasterFunction rasterInfoFunction = new RasterInfoFunctionClass();
IRasterInfoFunctionArguments rasterInfoFuncArgs = new RasterInfoFunctionArgumentsClass();
rasterInfoFuncArgs.Raster = inputRasterDataset;
rasterInfoFuncArgs.RasterInfo = idFrd.RasterInfo;
intermedFrd = new FunctionRasterDatasetClass();
intermedFrd.Init(rasterInfoFunction, rasterInfoFuncArgs);
}
else
return null;
// Check if there is an RPC file associated with the image. If so
// then add a geometric function to apply the rpc xform.
if (File.Exists(rpcPath))
opFrd = ApplyRPC(rpcPath, (IRasterDataset)intermedFrd);
// If no rpc pars exist or applying rpc fails, use the intermediate
// function raster dataset created.
if (opFrd == null)
opFrd = intermedFrd;
//IRasterFunction ebFunction = new ExtractBandFunctionClass();
//IRasterFunctionArguments ebFuncArgs = new ExtractBandFunctionArgumentsClass();
//ILongArray bandIDs = new LongArrayClass();
//bandIDs.Add(2);
//bandIDs.Add(1);
//bandIDs.Add(0);
////bandIDs.Add(4);
//((IExtractBandFunctionArguments)ebFuncArgs).BandIDs = bandIDs;
//((IExtractBandFunctionArguments)ebFuncArgs).Raster = inputRasterDataset;
//opFrd = new FunctionRasterDatasetClass();
//opFrd.Init(ebFunction, ebFuncArgs);
//if (opFrd == null)
//{
// IRasterFunction identityFunction = new IdentityFunctionClass();
// opFrd = new FunctionRasterDatasetClass();
// opFrd.Init(identityFunction, inputRasterDataset);
//}
}
catch (Exception exc)
{
string error = exc.Message;
}
return opFrd;
}
/// <summary>
/// Parse the RPC parameters file associated with the image and create an RPCXform
/// to bea applied to the inputDataset as a geomtric function.
/// </summary>
/// <param name="rpcPath">Path to the rpc parameters file.</param>
/// <param name="inputDataset">Input dataset to apply the xform on.</param>
/// <returns>Function raster dataset created.</returns>
private IFunctionRasterDataset ApplyRPC(string rpcPath, IRasterDataset inputDataset)
{
IFunctionRasterDataset opFrd = null;
try
{
// Open the RPC file and create Geometric transform
IGeodataXform finalXForm = null;
IRPCXform rpcXForm = GetRPCXForm(rpcPath);
IFunctionRasterDataset idFrd = null;
if (!(inputDataset is IFunctionRasterDataset))
{
IRasterFunction identityFunction = new IdentityFunctionClass();
idFrd = new FunctionRasterDatasetClass();
idFrd.Init(identityFunction, inputDataset);
}
else
idFrd = (IFunctionRasterDataset)inputDataset;
IRasterInfo datasetRasterInfo = idFrd.RasterInfo;
IEnvelope datasetExtent = datasetRasterInfo.Extent;
ISpatialReference datasetSrs = ((IGeoDataset)idFrd).SpatialReference;
long dRows = datasetRasterInfo.Height;
long dCols = datasetRasterInfo.Width;
IEnvelope pixelExtent = new EnvelopeClass();
pixelExtent.PutCoords(-0.5, 0.5 - dRows, -0.5 + dCols, 0.5);
bool noAffineNeeded = ((IClone)pixelExtent).IsEqual((IClone)datasetExtent);
if (!noAffineNeeded)
{
// Tranform ground space to pixel space.
IAffineTransformation2D affineXform = new AffineTransformation2DClass();
affineXform.DefineFromEnvelopes(datasetExtent, pixelExtent);
IGeometricXform geoXform = new GeometricXformClass();
geoXform.Transformation = affineXform;
finalXForm = geoXform;
}
// Transform from pixel space back to ground space to set as the forward transform.
IEnvelope groundExtent = ((IGeoDataset)idFrd).Extent;
groundExtent.Project(datasetSrs);
IAffineTransformation2D affineXform2 = new AffineTransformation2DClass();
affineXform2.DefineFromEnvelopes(pixelExtent, groundExtent);
IGeometricXform forwardXForm = new GeometricXformClass();
forwardXForm.Transformation = affineXform2;
rpcXForm.ForwardXform = forwardXForm;
// Create the composite transform that changes ground values to pixel space
// then applies the rpc transform which will transform them back to ground space.
ICompositeXform compositeXForm = new CompositeXformClass();
compositeXForm.Add(finalXForm);
compositeXForm.Add(rpcXForm);
finalXForm = (IGeodataXform)compositeXForm;
// Then apply the transform on the raster using the geometric function.
if (finalXForm != null)
{
IRasterFunction geometricFunction = new GeometricFunctionClass();
IGeometricFunctionArguments geometricFunctionArgs = null;
// Get the geomtric function arguments if supplied by the user (in the UI).
if (myRasterTypeOperation != null &&
((IRasterTypeProperties)myRasterTypeOperation).OrthorectificationParameters != null)
geometricFunctionArgs =
((IRasterTypeProperties)myRasterTypeOperation).OrthorectificationParameters;
else
geometricFunctionArgs = new GeometricFunctionArgumentsClass();
// Append the xform to the existing ones from the image.
geometricFunctionArgs.AppendGeodataXform = true;
geometricFunctionArgs.GeodataXform = finalXForm;
geometricFunctionArgs.Raster = inputDataset;
opFrd = new FunctionRasterDatasetClass();
opFrd.Init(geometricFunction, geometricFunctionArgs);
}
return opFrd;
}
catch (Exception exc)
{
string error = exc.Message;
return opFrd;
}
}
/// <summary>
/// Create an RPCXForm from a text file containing parameters.
/// </summary>
/// <param name="rpcFilePath">Text file containing the parameters.</param>
/// <returns>The RPCXForm generated.</returns>
private IRPCXform GetRPCXForm(string rpcFilePath)
{
try
{
// Array for parameters.
double[] RPC = new double[90];
// Propertyset to store properties as backup.
//IPropertySet coefficients = new PropertySetClass();
#region Parse RPC text file
// Use the stream reader to open the file and read lines from it.
using (StreamReader sr = new StreamReader(rpcFilePath))
{
string line;
int lineNumber = 0;
while ((line = sr.ReadLine()) != null)
{
++lineNumber;
try
{
// Split the line into tokens based on delimiters
char[] delimiters = { ':', ' ' };
string[] tokens = line.Split(delimiters, System.StringSplitOptions.RemoveEmptyEntries);
int numTokens = tokens.GetLength(0);
if (numTokens > 1)
{
string currPar = tokens[0];
double currValue = Convert.ToDouble(tokens[1]);
// Convert the Value to a double and store in the array.
RPC[(lineNumber - 1)] = currValue;
// Store the property and the value in the propertyset to lookup later if needed.
//coefficients.SetProperty(currPar, currValue);
// Read units for conversion if needed
//string currUnit = tokens[2];
}
else
Console.WriteLine("Could not parse line " + lineNumber.ToString());
}
catch (Exception ex)
{
Console.Write(ex.ToString());
}
}
sr.Close();
}
#endregion
// Create the new RPCXForm from the parameter array.
IRPCXform myRPCXform = (IRPCXform)new RPCXform();
object rpcCoeffs = ((object)RPC);
myRPCXform.DefineFromCoefficients(ref rpcCoeffs);
return myRPCXform;
}
catch (Exception exc)
{
string error = exc.Message;
throw exc;
}
}
/// <summary>
/// Create new fields to add to the mosaic dataset attribute table.
/// </summary>
/// <param name="myFields">Fields to be added.</param>
private void AddFields(IFields myFields)
{
// Create a new field object
IField pField = new FieldClass();
// Set the field editor for this field
IFieldEdit objectIDFieldEditor = (IFieldEdit)pField;
// Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SensorName";
objectIDFieldEditor.AliasName_2 = "Sensor Name";
// Set the type of the field
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeString;
// Add the newly created field to list of existing fields
IFieldsEdit fieldsEditor = (IFieldsEdit)myFields;
fieldsEditor.AddField(pField);
// Create a new field object
pField = new FieldClass();
// Set the field editor for this field
objectIDFieldEditor = (IFieldEdit)pField;
// Set the name and alias of the field
objectIDFieldEditor.Name_2 = "AcquisitionDate";
objectIDFieldEditor.AliasName_2 = "Acquisition Date";
// Set the type of the field
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDate;
fieldsEditor.AddField(pField);
// Create a new field object
pField = new FieldClass();
// Set the field editor for this field
objectIDFieldEditor = (IFieldEdit)pField;
// Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SunAzimuth";
objectIDFieldEditor.AliasName_2 = "Sun Azimuth";
// Set the type of the field
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldsEditor.AddField(pField);
// Create a new field object
pField = new FieldClass();
// Set the field editor for this field
objectIDFieldEditor = (IFieldEdit)pField;
// Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SunElevation";
objectIDFieldEditor.AliasName_2 = "Sun Elevation";
// Set the type of the field
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldsEditor.AddField(pField);
// Create a new field object
pField = new FieldClass();
// Set the field editor for this field
objectIDFieldEditor = (IFieldEdit)pField;
// Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SatAzimuth";
objectIDFieldEditor.AliasName_2 = "Satellite Azimuth";
// Set the type of the field as Blob
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldsEditor.AddField(pField);
// Create a new field object
pField = new FieldClass();
// Set the field editor for this field
objectIDFieldEditor = (IFieldEdit)pField;
// Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SatElevation";
objectIDFieldEditor.AliasName_2 = "Satellite Elevation";
// Set the type of the field as Blob
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldsEditor.AddField(pField);
}
#endregion
#region IRasterBuilderInit Members
public ISpatialReference DefaultSpatialReference
{
get
{
return myDefaultSpatialReference;
}
set
{
myDefaultSpatialReference = value;
}
}
public IMosaicDataset MosaicDataset
{
get
{
return myMosaicDataset;
}
set
{
myMosaicDataset = value;
}
}
public IRasterTypeOperation RasterTypeOperation
{
get
{
return myRasterTypeOperation;
}
set
{
myRasterTypeOperation = value;
}
}
public ITrackCancel TrackCancel
{
get
{
return myTrackCancel;
}
set
{
myTrackCancel = value;
}
}
#endregion
#region IPersistVariant Members
/// <summary>
/// UID for the object implementing the Persist Variant
/// </summary>
public UID ID
{
get { return myUID; }
}
/// <summary>
/// Load the object from the stream provided
/// </summary>
/// <param name="Stream">Stream that represents the serialized Raster Type</param>
public void Load(IVariantStream Stream)
{
string name = (string)Stream.Read();
//if (innerRasterBuilder is IPersistVariant)
// ((IPersistVariant)innerRasterBuilder).Load(Stream);
//innerRasterBuilder = (IRasterBuilder)Stream.Read(); // Load the innerRasterBuilder from the stream.
}
/// <summary>
/// Same the Raster Type to the stream provided
/// </summary>
/// <param name="Stream">Stream to serialize the Raster Type into</param>
public void Save(IVariantStream Stream)
{
Stream.Write("CustomRasterType");
//if (innerRasterBuilder is IPersistVariant)
// ((IPersistVariant)innerRasterBuilder).Save(Stream);
//Stream.Write(innerRasterBuilder); // Save the innerRasterBuilder into the stream.
}
#endregion
#region IRasterBuilder2 Members
/// <summary>
/// Check if the data source provided is a valid data source for the builder.
/// </summary>
/// <param name="vtDataSource">Data source (usually the path to a metadta file)</param>
/// <returns>Flag to specify whether it is valid source.</returns>
public bool CanBuild(object vtDataSource)
{
if (!(vtDataSource is string))
return false;
string dimFilePath = (string)vtDataSource;
if (!dimFilePath.ToLower().EndsWith(".dim"))
return false;
DiMapParser myDimParser = null;
try
{
myDimParser = new DiMapParser(dimFilePath);
if (myDimParser.MetadataProfile.ToLower() == "DMCII".ToLower())
{
myDimParser = null;
return true;
}
else
{
myDimParser = null;
return false;
}
}
catch (Exception exc)
{
myDimParser = null;
string error = exc.Message;
return false;
}
}
public bool CanMergeItems
{
get { return myCanMergeItems; }
}
public bool MergeItems
{
get
{
return myMergeItems;
}
set
{
myMergeItems = value;
}
}
/// <summary>
/// Check to see if the properties provided to the raster type/builder
/// are sufficient for it to work. Usually used for UI validation.
/// </summary>
public void Validate()
{
return;
}
#endregion
#region IRasterBuilderInit2 Members
/// <summary>
/// Helper object to store geographic transformations set on the mosaic dataset.
/// </summary>
public IGeoTransformationHelper GeoTransformationHelper
{
get
{
return myGeoTransformationHelper;
}
set
{
myGeoTransformationHelper = null;
}
}
#endregion
}
/// <summary>
/// Class used to parse the dim file (xml format) and get relevant properties from it.
/// </summary>
public class DiMapParser
{
private string myXmlPath;
private XmlDocument myXmlDoc;
private XmlNodeList bandInfo;
private XmlNodeList bandStats;
private XmlNodeList footprintInfo;
private int vertexCount;
public DiMapParser()
{
myXmlPath = null;
bandInfo = null;
bandStats = null;
footprintInfo = null;
vertexCount = 0;
}
public DiMapParser(string xmlPath)
{
myXmlPath = xmlPath;
bandInfo = null;
bandStats = null;
footprintInfo = null;
vertexCount = 0;
myXmlDoc = new XmlDocument();
myXmlDoc.Load(myXmlPath);
}
/// <summary>
/// Flag to specify whether the footprint exists in the xml file.
/// </summary>
public bool FootPrintExists
{
get
{
if (footprintInfo == null)
footprintInfo = myXmlDoc.SelectSingleNode("//Dataset_Frame").SelectNodes("Vertex");
return footprintInfo != null;
}
}
/// <summary>
/// Reset the vertex count to get vertices of the footprint.
/// </summary>
public void ResetVertexCount()
{
vertexCount = 0;
}
public bool GetNextVertex(out string x, out string y, out string col, out string row)
{
if (footprintInfo == null)
footprintInfo = myXmlDoc.SelectSingleNode("//Dataset_Frame").SelectNodes("Vertex");
x = footprintInfo[vertexCount].SelectSingleNode("FRAME_LON").InnerText;
y = footprintInfo[vertexCount].SelectSingleNode("FRAME_LAT").InnerText;
col = footprintInfo[vertexCount].SelectSingleNode("FRAME_COL").InnerText;
row = footprintInfo[vertexCount].SelectSingleNode("FRAME_ROW").InnerText;
++vertexCount;
if (vertexCount >= footprintInfo.Count)
return false;
else
return true;
}
/// <summary>
/// Get next vertex from the footprint defined in the xml based on the vertex count and unit.
/// </summary>
/// <param name="x">The X value.</param>
/// <param name="y">The Y value.</param>
/// <param name="unit">Unit to check which parameter to get vertex from.</param>
/// <returns>True if next vertex exists.</returns>
public bool GetNextVertex2(out string x, out string y, string unit)
{
if (unit == "Deg")
{
if (footprintInfo == null)
footprintInfo = myXmlDoc.SelectSingleNode("//Dataset_Frame").SelectNodes("Vertex");
x = footprintInfo[vertexCount].SelectSingleNode("FRAME_LON").InnerText;
y = footprintInfo[vertexCount].SelectSingleNode("FRAME_LAT").InnerText;
//col = footprintInfo[vertexCount].SelectSingleNode("FRAME_COL").InnerText;
//row = footprintInfo[vertexCount].SelectSingleNode("FRAME_ROW").InnerText;
}
else
{
if (footprintInfo == null)
footprintInfo = myXmlDoc.SelectSingleNode("//Dataset_Frame").SelectNodes("Vertex");
x = footprintInfo[vertexCount].SelectSingleNode("FRAME_X").InnerText;
y = footprintInfo[vertexCount].SelectSingleNode("FRAME_Y").InnerText;
//col = footprintInfo[vertexCount].SelectSingleNode("FRAME_COL").InnerText;
//row = footprintInfo[vertexCount].SelectSingleNode("FRAME_ROW").InnerText;
}
++vertexCount;
if (vertexCount >= footprintInfo.Count)
return false;
else
return true;
}
/// <summary>
/// The number of bands defined in the xml.
/// </summary>
public int NumBands
{
get
{
if (bandInfo == null)
bandInfo = myXmlDoc.SelectNodes("//Spectral_Band_Info");
if (bandStats == null)
bandStats = myXmlDoc.SelectNodes("//Band_Statistics");
return bandInfo.Count;
}
}
/// <summary>
/// Index of the band based on the counter.
/// </summary>
/// <param name="indexCounter">Counter (similar to vertexCount) to get the index for.</param>
/// <returns>Index of the band as string.</returns>
public string GetBandIndex(int indexCounter)
{
if (bandInfo == null)
bandInfo = myXmlDoc.SelectNodes("//Spectral_Band_Info");
return bandInfo[indexCounter].SelectSingleNode("BAND_INDEX").InnerText;
}
/// <summary>
/// Get the name of the band.
/// </summary>
/// <param name="bandIndex">Index of the band for which to get the name.</param>
/// <returns>Band name as string.</returns>
public string GetBandDesc(int bandIndex)
{
if (bandInfo == null)
bandInfo = myXmlDoc.SelectNodes("//Spectral_Band_Info");
return bandInfo[bandIndex - 1].SelectSingleNode("BAND_DESCRIPTION").InnerText;
}
/// <summary>
/// Get minimum value for the band.
/// </summary>
/// <param name="bandIndex">Index of the band for which to get the value.</param>
/// <returns>Value requested as string.</returns>
public string GetBandStatMin(int bandIndex)
{
if (bandStats == null)
bandStats = myXmlDoc.SelectNodes("//Band_Statistics");
return bandStats[bandIndex - 1].SelectSingleNode("STX_LIN_MIN").InnerText;
}
/// <summary>
/// Get maximum value for the band.
/// </summary>
/// <param name="bandIndex">Index of the band for which to get the value.</param>
/// <returns>Value requested as string.</returns>
public string GetBandStatMax(int bandIndex)
{
if (bandStats == null)
bandStats = myXmlDoc.SelectNodes("//Band_Statistics");
return bandStats[bandIndex - 1].SelectSingleNode("STX_LIN_MAX").InnerText;
}
/// <summary>
/// Get mean value for the band.
/// </summary>
/// <param name="bandIndex">Index of the band for which to get the value.</param>
/// <returns>Value requested as string.</returns>
public string GetBandStatMean(int bandIndex)
{
if (bandStats == null)
bandStats = myXmlDoc.SelectNodes("//Band_Statistics");
return bandStats[bandIndex - 1].SelectSingleNode("STX_MEAN").InnerText;
}
/// <summary>
/// Get standard deviation value for the band.
/// </summary>
/// <param name="bandIndex">Index of the band for which to get the value.</param>
/// <returns>Value requested as string.</returns>
public string GetBandStatStdDev(int bandIndex)
{
if (bandStats == null)
bandStats = myXmlDoc.SelectNodes("//Band_Statistics");
return bandStats[bandIndex - 1].SelectSingleNode("STX_STDV").InnerText;
}
/// <summary>
/// Get the product type for the dataset.
/// </summary>
public string ProductType
{
get
{
return myXmlDoc.SelectSingleNode("//PRODUCT_TYPE").InnerText;
}
}
/// <summary>
/// Get the sensor name for the dataset.
/// </summary>
public string MetadataProfile
{
get
{
return myXmlDoc.SelectSingleNode("//METADATA_PROFILE").InnerText;
}
}
/// <summary>
/// Get the geometric processing for the dataset.
/// </summary>
public string GeometricProcessing
{
get
{
return myXmlDoc.SelectSingleNode("//GEOMETRIC_PROCESSING").InnerText;
}
}
/// <summary>
/// Get the Acquisition Date for the dataset.
/// </summary>
public string AcquisitionDate
{
get
{
return myXmlDoc.SelectSingleNode("//IMAGING_DATE").InnerText;
}
}
/// <summary>
/// Get the Acquisition Time for the dataset.
/// </summary>
public string AcquisitionTime
{
get
{
return myXmlDoc.SelectSingleNode("//IMAGING_TIME").InnerText;
}
}
/// <summary>
/// Get the Sensor Angle for the dataset.
/// </summary>
public string IncidenceAngle
{
get
{
return myXmlDoc.SelectSingleNode("//INCIDENCE_ANGLE").InnerText;
}
}
/// <summary>
/// Get the Sun Azimuth for the dataset.
/// </summary>
public string SunAzimuth
{
get
{
return myXmlDoc.SelectSingleNode("//SUN_AZIMUTH").InnerText;
}
}
/// <summary>
/// Get the Sun Elevation for the dataset.
/// </summary>
public string SunElevation
{
get
{
return myXmlDoc.SelectSingleNode("//SUN_ELEVATION").InnerText;
}
}
/// <summary>
/// Get the epsg code for the spatial reference of the dataset.
/// </summary>
public string SrsCode
{
get
{
return myXmlDoc.SelectSingleNode("//HORIZONTAL_CS_CODE").InnerText;
}
}
/// <summary>
/// Get the Sensor Azimuth for the dataset.
/// </summary>
public string SensorAzimuth
{
get
{
XmlNodeList qualityAssessments = myXmlDoc.SelectNodes("//Quality_Assessment");
XmlNodeList qualityPars = qualityAssessments[1].SelectNodes("Quality_Parameter");
for (int i = 0; i < qualityPars.Count; ++i)
{
if (qualityPars[i].SelectSingleNode("QUALITY_PARAMETER_CODE").InnerText.Contains("SENSOR_AZIMUTH"))
return qualityPars[i].SelectSingleNode("QUALITY_PARAMETER_VALUE").InnerText;
}
return "";
}
}
}
}
[Visual Basic .NET]
DMCIIRasterType.vb
Imports System.IO
Imports System.Xml
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Runtime.InteropServices
Imports ESRI.ArcGIS.ADF
Imports ESRI.ArcGIS.DataSourcesRaster
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Carto
'
' *
' * This sample shows how to implement a Custom Raster Type to provide support for DMCII data.
' * Also provided is an optional test application to create a Geodatabase and a mosaic dataset
' * and add data using the custom type.
' * The main interface to be implemented is the IRasterBuilder interface along with
' * secondary interfaces such as IRasterBuilderInit (which provides access to the parent MD),
' * IPersistvariant (which implements persistence), IRasterBuilderInit2 and IRasterBuilder2
' * (new interfaces added at 10.1).
' * A IRasterFactory implementation also needs to be created in order for the Raster type to
' * show up in the list of Raster Types in the Add Rasters GP Tool. The factory is responsible
' * for creating the raster type object and setting some properties on it. It also enables the
' * use of the Raster Product.
' *
'
<Guid("5DEF8E3C-51E9-49af-A3BE-EF8C68A4BBBE")> _
<ClassInterface(ClassInterfaceType.None)> _
<ProgId("SampleRasterType.CustomRasterTypeFactory")> _
<ComVisible(True)> _
Public Class DMCIIRasterTypeFactory
Implements IRasterTypeFactory
#Region "Private Members"
Private myRasterTypeNames As IStringArray
' List of Raster Types that the factory can create.
Private myUID As UID
' UID for the DMCII Raster Type.
#End Region
#Region "IRasterTypeFactory Members"
Public Sub New()
Dim rasterTypeName As String = "DMCII Raster Type"
myRasterTypeNames = New StrArrayClass()
myRasterTypeNames.Add(rasterTypeName)
myUID = New UIDClass()
myUID.Value = "{5DEF8E3C-51E9-49af-A3BE-EF8C68A4BBBE}"
End Sub
Public ReadOnly Property CLSID() As UID Implements IRasterTypeFactory.CLSID
Get
Return myUID
End Get
End Property
''' <summary>
''' Create a Raster Type object given the name of the raster type (usually
''' the same name as the one in the UI list of raster types).
''' </summary>
''' <param name="RasterTypeName">Name of the Raster Type object to create.</param>
''' <returns>The Raster type object.</returns>
Public Function CreateRasterType(RasterTypeName As String) As IRasterType Implements IRasterTypeFactory.CreateRasterType
' Create a new RasterType object and its corresponding name object.
Dim theRasterType As IRasterType = New RasterTypeClass()
Dim theRasterTypeName As IRasterTypeName = New RasterTypeNameClass()
theRasterTypeName.Name = RasterTypeName
theRasterType.FullName = DirectCast(theRasterTypeName, IName)
' Set the properties for the raster type object. These are shown in the
' 'General' tab of the raster type properties page.
DirectCast(theRasterType, IRasterTypeProperties).Name = "DMCII Raster Type"
DirectCast(theRasterType, IRasterTypeProperties).Description = "Raster Type for DMCII data."
DirectCast(theRasterType, IRasterTypeProperties).DataSourceFilter = "*.dim"
DirectCast(theRasterType, IRasterTypeProperties).SupportsOrthorectification = True
' Create the Custom Raster Builder object
Dim customRasterBuilder As IRasterBuilder = New DMCIIRasterBuilder()
' Set the Raster Builder of theRasterType to the above created builder.
theRasterType.RasterBuilder = customRasterBuilder
' Enable the use of the Raster Type as a Raster Product.
DirectCast(theRasterType, IRasterTypeProperties2).IsSensorRasterType = True
'#Region "Set Product Templates"
' Create a new array of templates if needed.
If theRasterType.ItemTemplates Is Nothing Then
theRasterType.ItemTemplates = New ItemTemplateArrayClass()
End If
' Add a 'Raw' template.
Dim nullTemplate As IItemTemplate = New ItemTemplateClass()
nullTemplate.Enabled = False
nullTemplate.Name = "Raw"
DirectCast(nullTemplate, IItemTemplate2).IsSensorTemplate = True
DirectCast(nullTemplate, IItemTemplate2).SupportsEnhancement = False
theRasterType.ItemTemplates.Add(nullTemplate)
' Add a 'Stretch' template. This is the default template.
Dim strTemplate As IItemTemplate = New ItemTemplateClass()
strTemplate.Enabled = True
strTemplate.Name = "Stretch"
Dim stretchFunction As IRasterFunction = New StretchFunctionClass()
Dim stretchFunctionArgs As IStretchFunctionArguments = New StretchFunctionArgumentsClass()
stretchFunctionArgs.StretchType = esriRasterStretchType.esriRasterStretchMinimumMaximum
Dim rasterVar As IRasterFunctionVariable = New RasterFunctionVariableClass()
rasterVar.IsDataset = True
rasterVar.Name = "MS"
rasterVar.Aliases = New StrArrayClass()
rasterVar.Aliases.Add("MS")
rasterVar.Description = "Variable for input raster"
stretchFunctionArgs.Raster = rasterVar
Dim stretchFunctionTemplate As IRasterFunctionTemplate = New RasterFunctionTemplateClass()
stretchFunctionTemplate.[Function] = stretchFunction
stretchFunctionTemplate.Arguments = stretchFunctionArgs
strTemplate.RasterFunctionTemplate = stretchFunctionTemplate
DirectCast(strTemplate, IItemTemplate2).IsSensorTemplate = True
DirectCast(strTemplate, IItemTemplate2).SupportsEnhancement = True
theRasterType.ItemTemplates.Add(strTemplate)
'#End Region
'#Region "Set Product Types"
' Add Product types (called URI filters in the code).
If DirectCast(theRasterType, IRasterTypeProperties).SupportedURIFilters Is Nothing Then
DirectCast(theRasterType, IRasterTypeProperties).SupportedURIFilters = New ArrayClass()
End If
' Create and setup URI Filters
Dim allFilter As IItemURIFilter = New URIProductNameFilterClass()
allFilter.Name = "All"
allFilter.SupportsOrthorectification = True
allFilter.SupportedTemplateNames = New StrArrayClass()
allFilter.SupportedTemplateNames.Add("Raw")
allFilter.SupportedTemplateNames.Add("Stretch")
Dim allProductNames As IStringArray = New StrArrayClass()
allProductNames.Add("L1T")
allProductNames.Add("L1R")
DirectCast(allFilter, IURIProductNameFilter).ProductNames = allProductNames
' The L1T filter does not support orthorectification.
Dim l1tFilter As IItemURIFilter = New URIProductNameFilterClass()
l1tFilter.Name = "L1T"
l1tFilter.SupportsOrthorectification = False
l1tFilter.SupportedTemplateNames = New StrArrayClass()
l1tFilter.SupportedTemplateNames.Add("Raw")
l1tFilter.SupportedTemplateNames.Add("Stretch")
Dim l1tProductNames As IStringArray = New StrArrayClass()
l1tProductNames.Add("L1T")
DirectCast(l1tFilter, IURIProductNameFilter).ProductNames = l1tProductNames
Dim l1rFilter As IItemURIFilter = New URIProductNameFilterClass()
l1rFilter.Name = "L1R"
l1rFilter.SupportsOrthorectification = True
l1rFilter.SupportedTemplateNames = New StrArrayClass()
l1rFilter.SupportedTemplateNames.Add("Raw")
l1rFilter.SupportedTemplateNames.Add("Stretch")
Dim l1rProductNames As IStringArray = New StrArrayClass()
l1rProductNames.Add("L1R")
DirectCast(l1rFilter, IURIProductNameFilter).ProductNames = l1rProductNames
' Add them to the supported uri filters list
DirectCast(theRasterType, IRasterTypeProperties).SupportedURIFilters.Add(allFilter)
DirectCast(theRasterType, IRasterTypeProperties).SupportedURIFilters.Add(l1tFilter)
DirectCast(theRasterType, IRasterTypeProperties).SupportedURIFilters.Add(l1rFilter)
' Set 'All' as default
theRasterType.URIFilter = allFilter
'#End Region
Return theRasterType
End Function
''' <summary>
''' Name of the Raster Type Factory
''' </summary>
Public ReadOnly Property Name() As String Implements IRasterTypeFactory.Name
Get
Return "Custom Raster Type Factory"
End Get
End Property
''' <summary>
''' Names of the Raster Types supported by the factory.
''' </summary>
Public ReadOnly Property RasterTypeNames() As IStringArray Implements IRasterTypeFactory.RasterTypeNames
Get
Return myRasterTypeNames
End Get
End Property
#End Region
#Region "COM Registration Function(s)"
<ComRegisterFunction> _
Private Shared Sub Reg(regKey As String)
ESRI.ArcGIS.ADF.CATIDs.RasterTypeFactory.Register(regKey)
End Sub
<ComUnregisterFunction> _
Private Shared Sub Unreg(regKey As String)
ESRI.ArcGIS.ADF.CATIDs.RasterTypeFactory.Unregister(regKey)
End Sub
#End Region
End Class
<Guid("316725CB-35F2-4159-BEBB-A1445ECE9CF1")> _
<ClassInterface(ClassInterfaceType.None)> _
<ProgId("SampleRasterType.CustomRasterType")> _
<ComVisible(True)> _
Public Class DMCIIRasterBuilder
Implements IRasterBuilder
Implements IRasterBuilderInit
Implements IPersistVariant
Implements IRasterBuilder2
Implements IRasterBuilderInit2
#Region "Private Members"
' The Mosaic Dataset currently using the Raster Type.
Private myMosaicDataset As IMosaicDataset
' The default spatial reference to apply to added data (if no spatial reference exists).
Private myDefaultSpatialReference As ISpatialReference
' The Raster Type Operation object (usually a Raster Type object).
Private myRasterTypeOperation As IRasterTypeOperation
' The Raster Type Properties.
Private myRasterTypeProperties As IPropertySet
' Array to fill with ItemURI's.
Private myURIArray As IItemURIArray
' GeoTransform helper object.
Private myGeoTransformationHelper As IGeoTransformationHelper
' Flags to specify whether the Raster Type can merge items and
Private myCanMergeItems As Boolean
' if it has merged item.
Private myMergeItems As Boolean
' Mapping from field names to names or properties in the item propertyset.
Private myAuxiliaryFieldAlias As IPropertySet
' Fields to add to the Mosaic Dataset when items are added through this Raster Type.
Private myAuxiliaryFields As IFields
Private myTrackCancel As ITrackCancel
Private myUID As UID
' UID for the Custom Builder.
' The current dimap file being processed.
Private myCurrentDimFile As String
#End Region
Public Sub New()
myMosaicDataset = Nothing
myDefaultSpatialReference = Nothing
myRasterTypeOperation = Nothing
myRasterTypeProperties = Nothing
myTrackCancel = Nothing
myURIArray = Nothing
myGeoTransformationHelper = Nothing
myCanMergeItems = False
myMergeItems = False
myAuxiliaryFieldAlias = Nothing
myAuxiliaryFields = Nothing
myUID = New UIDClass()
myUID.Value = "{316725CB-35F2-4159-BEBB-A1445ECE9CF1}"
End Sub
#Region "IRasterBuilder Members"
''' <summary>
''' This defines a mapping from field names in the attribute table of the mosaic to
''' properties in the property set associated with the dataset, incase a user wants
''' specify fields which are different from the property in the dataset.
''' e.g. The field CloudCover may map to a property called C_C in the dataset built
''' by the builder.
''' </summary>
Public Property AuxiliaryFieldAlias() As IPropertySet Implements IRasterBuilder.AuxiliaryFieldAlias, IRasterBuilder2.AuxiliaryFieldAlias
Get
Return myAuxiliaryFieldAlias
End Get
Set
myAuxiliaryFieldAlias = value
End Set
End Property
''' <summary>
''' Specify fields if necessary to be added to the Mosaic Dataset when
''' items are added throug hthis Raster Type.
''' </summary>
Public Property AuxiliaryFields() As IFields Implements IRasterBuilder.AuxiliaryFields, IRasterBuilder2.AuxiliaryFields
Get
If myAuxiliaryFields Is Nothing Then
myAuxiliaryFields = New FieldsClass()
AddFields(myAuxiliaryFields)
End If
Return myAuxiliaryFields
End Get
Set
myAuxiliaryFields = value
End Set
End Property
''' <summary>
''' Get a crawler recommended by the Raster Type based on the data srouce properties provided.
''' </summary>
''' <param name="pDataSourceProperties">Data source properties.</param>
''' <returns>Data source crawler recommended by the raster type.</returns>
Public Function GetRecommendedCrawler(pDataSourceProperties As IPropertySet) As IDataSourceCrawler Implements IRasterBuilder.GetRecommendedCrawler, IRasterBuilder2.GetRecommendedCrawler
Try
' This is usually a file crawler because it can crawl directories as well, unless
' special types of data needs to be crawled.
Dim myCrawler As IDataSourceCrawler = New FileCrawlerClass()
DirectCast(myCrawler, IFileCrawler).Path = Convert.ToString(pDataSourceProperties.GetProperty("Source"))
DirectCast(myCrawler, IFileCrawler).Recurse = Convert.ToBoolean(pDataSourceProperties.GetProperty("Recurse"))
myCrawler.Filter = Convert.ToString(pDataSourceProperties.GetProperty("Filter"))
If myCrawler.Filter Is Nothing OrElse myCrawler.Filter = "" Then
myCrawler.Filter = "*.dim"
End If
Return myCrawler
Catch generatedExceptionName As Exception
Throw
End Try
End Function
''' <summary>
''' Prepare the Raster Type for generating item Unique Resource Identifier (URI)
''' </summary>
''' <param name="pCrawler">Crawler to use to generate the item URI's</param>
Public Sub BeginConstruction(pCrawler As IDataSourceCrawler) Implements IRasterBuilder.BeginConstruction, IRasterBuilder2.BeginConstruction
myURIArray = New ItemURIArrayClass()
End Sub
''' <summary>
''' Construct a Unique Resource Identifier (URI)
''' for each crawler item
''' </summary>
''' <param name="crawlerItem">Crawled Item from which the URI is generated</param>
Public Sub ConstructURIs(crawlerItem As Object) Implements IRasterBuilder.ConstructURIs, IRasterBuilder2.ConstructURIs
myCurrentDimFile = DirectCast(crawlerItem, String)
End Sub
''' <summary>
''' Finish construction of the URI's
''' </summary>
''' <returns>Array containing finised URI's</returns>
Public Function EndConstruction() As IItemURIArray Implements IRasterBuilder.EndConstruction, IRasterBuilder2.EndConstruction
Return myURIArray
End Function
''' <summary>
''' Generate the next URI.
''' </summary>
''' <returns>The URI generated.</returns>
Public Function GetNextURI() As IItemURI Implements IRasterBuilder.GetNextURI, IRasterBuilder2.GetNextURI
Dim newURI As IItemURI = Nothing
Try
' Check to see if the item cralwed is a .dim file.
If myCurrentDimFile <> "" AndAlso myCurrentDimFile IsNot Nothing AndAlso myCurrentDimFile.EndsWith(".dim") Then
' Create a new Dimap Parser obect and item uri.
Dim myDimParser As New DiMapParser(myCurrentDimFile)
newURI = New ItemURIClass()
' Set the display name, Group, Product Name, Tag and Key.
newURI.DisplayName = System.IO.Path.GetFileName(myCurrentDimFile)
newURI.Group = System.IO.Path.GetFileNameWithoutExtension(myCurrentDimFile)
newURI.Key = myCurrentDimFile
newURI.ProductName = myDimParser.ProductType
newURI.Tag = "MS"
' Set the timestamp of the dimfile as source time stamp. This helps
' with synchronization later.
Dim myEnv As IRasterTypeEnvironment = New RasterTypeEnvironmentClass()
Dim dimTS As DateTime = myEnv.GetTimeStamp(myCurrentDimFile)
newURI.SourceTimeStamp = dimTS
myDimParser = Nothing
myCurrentDimFile = ""
myURIArray.Add(newURI)
End If
Catch generatedExceptionName As Exception
Throw
End Try
Return newURI
End Function
''' <summary>
''' Build the Builder Item which includes the function raster dataset and its footprint
''' given the ItemURI.
''' </summary>
''' <param name="pItemURI">ItemURi to use to build the Builder Item.</param>
''' <returns>The builder item.</returns>
Public Function Build(pItemURI As IItemURI) As IBuilderItem Implements IRasterBuilder.Build, IRasterBuilder2.Build
Try
' Create a new parser object and builder item.
Dim myDimParser As New DiMapParser(pItemURI.Key)
Dim currItem As IBuilderItem = New BuilderItemClass()
' Set Category and URI
currItem.Category = esriRasterCatalogItemCategory.esriRasterCatalogItemCategoryPrimary
currItem.URI = pItemURI
' Set FunctionRasterDataset
Dim inputFrd As IFunctionRasterDataset = GetFRD(myDimParser, pItemURI)
currItem.Dataset = inputFrd
' Set band information for the function dataset including names, wavelengths and stats if available.
SetBandProperties(DirectCast(inputFrd, IDataset), myDimParser)
' Set Footprint
Dim geoDset As IGeoDataset = DirectCast(inputFrd, IGeoDataset)
' Set it to the current raster extent first. If the raster has no
' spatial reference, the extents will be in pixel space.
currItem.Footprint = DirectCast(geoDset.Extent, IGeometry)
' The get the footprint from the dim file is it exists.
currItem.Footprint = GetFootprint(myDimParser)
' Set Properties. These properties are used to fill the Auxiliary Fields
' defined earlier and also key properties if the names are correct.
Dim propSet As IPropertySet = currItem.Dataset.Properties
If propSet Is Nothing Then
propSet = New PropertySetClass()
End If
Dim sunAzimuth As Double = Convert.ToDouble(myDimParser.SunAzimuth)
Dim sunElevation As Double = Convert.ToDouble(myDimParser.SunElevation)
Dim sensorAzimuth As Double = Convert.ToDouble(myDimParser.SensorAzimuth)
Dim sensorElevation As Double = 180 - Convert.ToDouble(myDimParser.IncidenceAngle)
Dim acqDate As String = myDimParser.AcquisitionDate
Dim acqTime As String = myDimParser.AcquisitionTime
' Create a time object from the provided date and time.
Dim acqDateTimeObj As ITime = New TimeClass()
acqDateTimeObj.SetFromTimeString(esriTimeStringFormat.esriTSFYearThruSubSecondWithDash, acqDate & " " & acqTime)
' and obtain a DateTime object to set as value of the property. This ensures the
' field displays the value correctly.
Dim acqDateTimeFieldVal As DateTime = acqDateTimeObj.QueryOleTime()
propSet.SetProperty("AcquisitionDate", acqDateTimeFieldVal)
propSet.SetProperty("SensorName", myDimParser.MetadataProfile)
propSet.SetProperty("SunAzimuth", sunAzimuth)
propSet.SetProperty("SunElevation", sunElevation)
propSet.SetProperty("SatAzimuth", sensorAzimuth)
propSet.SetProperty("SatElevation", sensorElevation)
currItem.Dataset.Properties = propSet
Return currItem
Catch exc As Exception
Throw exc
End Try
End Function
''' <summary>
''' Flag to specify whether the Raster Builder can build items in place.
''' </summary>
Public ReadOnly Property CanBuildInPlace() As Boolean Implements IRasterBuilder.CanBuildInPlace, IRasterBuilder2.CanBuildInPlace
Get
Return False
End Get
End Property
''' <summary>
''' Check if the item provided is "stale" or not valid
''' </summary>
''' <param name="pItemURI">URI for the item to be checked</param>
''' <returns>Flag to specify whether the item is stale or not.</returns>
Public Function IsStale(pItemURI As IItemURI) As Boolean Implements IRasterBuilder.IsStale, IRasterBuilder2.IsStale
Try
Dim myEnv As IRasterTypeEnvironment = New RasterTypeEnvironmentClass()
Dim currDimTS As DateTime = myEnv.GetTimeStamp(pItemURI.Key)
Return pItemURI.SourceTimeStamp <> currDimTS
Catch generatedExceptionName As Exception
Throw
End Try
End Function
''' <summary>
''' Properties associated with the Raster Type
''' </summary>
Public Property Properties() As IPropertySet Implements IRasterBuilder.Properties, IRasterBuilder2.Properties
Get
If myRasterTypeProperties Is Nothing Then
myRasterTypeProperties = New PropertySetClass()
End If
Return myRasterTypeProperties
End Get
Set
myRasterTypeProperties = value
End Set
End Property
''' <summary>
''' Sets band properties on a given dataset including stats, band names and wavelengths.
''' </summary>
''' <param name="dataset">The dataset to set properties on.</param>
''' <param name="dimParser">Dimap parser to read properties from.</param>
Private Sub SetBandProperties(dataset As IDataset, dimParser As DiMapParser)
Try
' Set band band props.
Dim rasterKeyProps As IRasterKeyProperties = DirectCast(dataset, IRasterKeyProperties)
Dim rasterBandColl As IRasterBandCollection = DirectCast(dataset, IRasterBandCollection)
Dim imageNumBands As Integer = DirectCast(dataset, IFunctionRasterDataset).RasterInfo.BandCount
Dim dinNumBands As Integer = dimParser.NumBands
Dim bandIndexes As Integer() = New Integer(dinNumBands - 1) {}
Dim bandNames As IStringArray = New StrArrayClass()
For i As Integer = 0 To dinNumBands - 1
' Get band index for the first band.
bandIndexes(i) = Convert.ToInt16(dimParser.GetBandIndex(i))
' Validate band index.
If bandIndexes(i) > 0 AndAlso bandIndexes(i) <= imageNumBands Then
' Get Band Name for the index.
bandNames.Add(dimParser.GetBandDesc(bandIndexes(i)))
' Get Band stats for the index.
Dim bandStats As IRasterStatistics = New RasterStatisticsClass()
bandStats.Minimum = Convert.ToDouble(dimParser.GetBandStatMin(bandIndexes(i)))
bandStats.Maximum = Convert.ToDouble(dimParser.GetBandStatMax(bandIndexes(i)))
bandStats.Mean = Convert.ToDouble(dimParser.GetBandStatMean(bandIndexes(i)))
bandStats.StandardDeviation = Convert.ToDouble(dimParser.GetBandStatStdDev(bandIndexes(i)))
' Set stats on the dataset.
DirectCast(rasterBandColl.Item(bandIndexes(i) - 1), IRasterBandEdit2).AlterStatistics(bandStats)
' Set Band Name and wavelengths according to the name.
rasterKeyProps.SetBandProperty("BandName", (bandIndexes(i) - 1), bandNames.Element(i))
SetBandWavelengths(dataset, (bandIndexes(i) - 1))
' Refresh dataset so changes are saved.
DirectCast(dataset, IRasterDataset3).Refresh()
End If
Next
Catch exc As Exception
Dim [error] As String = exc.Message
End Try
End Sub
''' <summary>
''' Set the wavelengths corresponding to the band name.
''' </summary>
Private Sub SetBandWavelengths(dataset As IDataset, bandIndex As Integer)
Dim rasterKeyProps As IRasterKeyProperties = DirectCast(dataset, IRasterKeyProperties)
Dim rasterBandColl As IRasterBandCollection = DirectCast(dataset, IRasterBandCollection)
Dim bandName As String = DirectCast(rasterKeyProps.GetBandProperty("BandName", bandIndex), String)
' Set wavelengths for the bands
Select Case bandName.ToLower()
Case "red"
If True Then
rasterKeyProps.SetBandProperty("WavelengthMin", bandIndex, 630)
rasterKeyProps.SetBandProperty("WavelengthMax", bandIndex, 690)
End If
Exit Select
Case "green"
If True Then
rasterKeyProps.SetBandProperty("WavelengthMin", bandIndex, 520)
rasterKeyProps.SetBandProperty("WavelengthMax", bandIndex, 600)
End If
Exit Select
Case "nir", "nearinfrared"
If True Then
rasterKeyProps.SetBandProperty("WavelengthMin", bandIndex, 770)
rasterKeyProps.SetBandProperty("WavelengthMax", bandIndex, 900)
End If
Exit Select
End Select
End Sub
'private IGeometry GetFootprint(DiMapParser dimParser)
'{
' IGeometry currFootprint = null;
' dimParser.ResetVertexCount();
' string xs = "";
' string ys = "";
' string rows = "";
' string cols = "";
' double minX = 10000000000.0;
' double maxX = -1000000000.00;
' double minY = 1000000000.00;
' double maxY = -1000000000.00;
' double minRow = 1000000000.00;
' double maxRow = -1000000000.0;
' double minCol = 1000000000.00;
' double maxCol = -1000000000.0;
' double x = 0.0;
' double y = 0.0;
' double row = 0.0;
' double col = 0.0;
' while (dimParser.GetNextVertex(out xs, out ys, out rows, out cols))
' {
' x = Convert.ToDouble(xs);
' y = Convert.ToDouble(ys);
' row = Convert.ToDouble(rows);
' col = Convert.ToDouble(cols);
' if (x < minX)
' minX = x;
' if (x > maxX)
' maxX = x;
' if (y < minY)
' minY = y;
' if (y > maxY)
' maxY = y;
' if (row < minRow)
' minRow = row;
' if (row > maxRow)
' maxRow = row;
' if (col < minCol)
' minCol = col;
' if (col > maxCol)
' maxCol = col;
' x = 0.0;
' y = 0.0;
' row = 0.0;
' col = 0.0;
' xs = "";
' ys = "";
' rows = "";
' cols = "";
' }
' x = Convert.ToDouble(xs);
' y = Convert.ToDouble(ys);
' row = Convert.ToDouble(rows);
' col = Convert.ToDouble(cols);
' if (x < minX)
' minX = x;
' if (x > maxX)
' maxX = x;
' if (y < minY)
' minY = y;
' if (y > maxY)
' maxY = y;
' if (row < minRow)
' minRow = row;
' if (row > maxRow)
' maxRow = row;
' if (col < minCol)
' minCol = col;
' if (col > maxCol)
' maxCol = col;
' currFootprint = new PolygonClass();
' IPointCollection currPointColl = (IPointCollection)currFootprint;
' IEnvelope rectEnvelope = new EnvelopeClass();
' rectEnvelope.PutCoords(minX, minY, maxX, maxY);
' ISegmentCollection segmentCollection = (ISegmentCollection)currFootprint;
' segmentCollection.SetRectangle(rectEnvelope);
' // Get Srs
' int epsgcode = Convert.ToInt32((dimParser.SrsCode.Split(':'))[1]);
' ISpatialReferenceFactory3 srsfactory = new SpatialReferenceEnvironmentClass();
' ISpatialReference dimSrs = srsfactory.CreateSpatialReference(epsgcode);
' ISpatialReferenceResolution srsRes = (ISpatialReferenceResolution)dimSrs;
' srsRes.ConstructFromHorizon();
' srsRes.SetDefaultXYResolution();
' ((ISpatialReferenceTolerance)dimSrs).SetDefaultXYTolerance();
' currFootprint.SpatialReference = dimSrs;
' #region Commented
' //IEnvelope extent = new EnvelopeClass();
' //extent.XMin = geoDset.Extent.XMin;
' //extent.XMax = geoDset.Extent.XMax;
' //extent.YMin = geoDset.Extent.YMin;
' //extent.YMax = geoDset.Extent.YMax;
' //extent.SpatialReference = geoDset.SpatialReference;
' //extent.Width = inputFrd.RasterInfo.Extent.Width;
' //extent.Height = inputFrd.RasterInfo.Extent.Height;
' //currItem.Footprint = (IGeometry)extent;
' //myDimParser.ResetVertexCount();
' //string x = "";
' //string y = "";
' //string row = "";
' //string col = "";
' //IGeometry currFootprint = new PolygonClass();
' //IPointCollection currPointColl = (IPointCollection)currFootprint;
' // Creating a polygon!!!
' ////Build a polygon from a sequence of points.
' ////Add arrays of points to a geometry using the IGeometryBridge2 interface on the
' ////GeometryEnvironment singleton object.
' //IGeometryBridge2 geometryBridge2 = new GeometryEnvironmentClass();
' //IPointCollection4 pointCollection4 = new PolygonClass();
' ////TODO:
' ////pointCollection4.SpatialReference = 'Define the spatial reference of the new polygon.
' //WKSPoint[] aWKSPointBuffer = null;
' //long cPoints = 4; //The number of points in the first part.
' //aWKSPointBuffer = new WKSPoint[System.Convert.ToInt32(cPoints - 1) + 1];
' ////TODO:
' ////aWKSPointBuffer = 'Read cPoints into the point buffer.
' //geometryBridge2.SetWKSPoints(pointCollection4, ref aWKSPointBuffer);
' //myDimParser.GetNextVertex(out x, out y, out col, out row);
' //IPoint currPoint1 = new PointClass();
' //currPoint1.X = Convert.ToDouble(x);
' //currPoint1.Y = Convert.ToDouble(y);
' //myDimParser.GetNextVertex(out x, out y, out col, out row);
' //IPoint currPoint2 = new PointClass();
' //currPoint1.X = Convert.ToDouble(x);
' //currPoint1.Y = Convert.ToDouble(y);
' //myDimParser.GetNextVertex(out x, out y, out col, out row);
' //IPoint currPoint3 = new PointClass();
' //currPoint1.X = Convert.ToDouble(x);
' //currPoint1.Y = Convert.ToDouble(y);
' //myDimParser.GetNextVertex(out x, out y, out col, out row);
' //IPoint currPoint4 = new PointClass();
' //currPoint1.X = Convert.ToDouble(x);
' //currPoint1.Y = Convert.ToDouble(y);
' //object refPoint1 = (object)currPoint1;
' //object refPoint2 = (object)currPoint2;
' //object refPoint3 = (object)currPoint3;
' //object refPoint4 = (object)currPoint4;
' //currPointColl.AddPoint(currPoint1, ref refPoint4, ref refPoint2);
' //currPointColl.AddPoint(currPoint2, ref refPoint1, ref refPoint3);
' //currPointColl.AddPoint(currPoint3, ref refPoint2, ref refPoint4);
' //currPointColl.AddPoint(currPoint4, ref refPoint3, ref refPoint1);
' //((IPolygon)currFootprint).Close();
' //currFootprint.SpatialReference = dimSrs;
' #endregion
' return currFootprint;
'}
''' <summary>
''' Get the footprint from the dimap file if it exists.
''' </summary>
''' <param name="dimParser">Dimap file parser.</param>
''' <returns>Footprint geomtry.</returns>
Private Function GetFootprint(dimParser As DiMapParser) As IGeometry
Dim currFootprint As IGeometry = Nothing
dimParser.ResetVertexCount()
Dim xs As String = ""
Dim ys As String = ""
Dim minX As Double = 10000000000.0
Dim maxX As Double = -1000000000.0
Dim minY As Double = 1000000000.0
Dim maxY As Double = -1000000000.0
Dim x As Double = 0.0
Dim y As Double = 0.0
Dim units As String = dimParser.ProductType
If units.ToLower() = "L1T".ToLower() Then
units = "M"
ElseIf units.ToLower() = "L1R".ToLower() Then
units = "Deg"
End If
' Get vertices from the dimap file and figure out the min,max.
While dimParser.GetNextVertex2(xs, ys, units)
x = Convert.ToDouble(xs)
y = Convert.ToDouble(ys)
If x < minX Then
minX = x
End If
If x > maxX Then
maxX = x
End If
If y < minY Then
minY = y
End If
If y > maxY Then
maxY = y
End If
x = 0.0
y = 0.0
xs = ""
ys = ""
End While
x = Convert.ToDouble(xs)
y = Convert.ToDouble(ys)
If x < minX Then
minX = x
End If
If x > maxX Then
maxX = x
End If
If y < minY Then
minY = y
End If
If y > maxY Then
maxY = y
End If
' create a new polygon and fill it using the vertices calculated.
currFootprint = New PolygonClass()
Dim currPointColl As IPointCollection = DirectCast(currFootprint, IPointCollection)
Dim rectEnvelope As IEnvelope = New EnvelopeClass()
rectEnvelope.PutCoords(minX, minY, maxX, maxY)
Dim segmentCollection As ISegmentCollection = DirectCast(currFootprint, ISegmentCollection)
segmentCollection.SetRectangle(rectEnvelope)
' Get Srs from the dim file and set it on the footprint.
Dim epsgcode As Integer = Convert.ToInt32((dimParser.SrsCode.Split(":"C))(1))
Dim srsfactory As ISpatialReferenceFactory3 = New SpatialReferenceEnvironmentClass()
Dim dimSrs As ISpatialReference = srsfactory.CreateSpatialReference(epsgcode)
Dim srsRes As ISpatialReferenceResolution = DirectCast(dimSrs, ISpatialReferenceResolution)
srsRes.ConstructFromHorizon()
srsRes.SetDefaultXYResolution()
DirectCast(dimSrs, ISpatialReferenceTolerance).SetDefaultXYTolerance()
currFootprint.SpatialReference = dimSrs
Return currFootprint
End Function
''' <summary>
''' Create the function raster dataset from the source images.
''' </summary>
''' <param name="dimPar">Parser for the dimap file.</param>
''' <param name="pItemURI">ItemURi to use.</param>
''' <returns>Function raster dataset created.</returns>
Private Function GetFRD(dimPar As DiMapParser, pItemURI As IItemURI) As IFunctionRasterDataset
Dim opFrd As IFunctionRasterDataset = Nothing
Try
Dim factoryType As Type = Type.GetTypeFromProgID("esriDataSourcesRaster.RasterWorkspaceFactory")
Dim workspaceFactory As IWorkspaceFactory = DirectCast(Activator.CreateInstance(factoryType), IWorkspaceFactory)
Dim workspace As IWorkspace = workspaceFactory.OpenFromFile(System.IO.Path.GetDirectoryName(pItemURI.Key), 0)
Dim rasterWorkspace As IRasterWorkspace = DirectCast(workspace, IRasterWorkspace)
' Open the tif file associated with the .dim file as a raster dataset.
Dim imagePath As String = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(pItemURI.Key), pItemURI.Group & ".tif")
Dim rpcPath As String = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(pItemURI.Key), pItemURI.Group & ".rpc")
Dim inputRasterDataset As IRasterDataset = Nothing
If File.Exists(imagePath) Then
inputRasterDataset = rasterWorkspace.OpenRasterDataset(pItemURI.Group & ".tif")
Else
Return Nothing
End If
Dim intermedFrd As IFunctionRasterDataset = Nothing
' If the file opes successfully, add a RasterInfo function on top.
If inputRasterDataset IsNot Nothing Then
' Create an Identity function dataset to get the raster info.
Dim identityFunction As IRasterFunction = New IdentityFunctionClass()
Dim idFrd As IFunctionRasterDataset = New FunctionRasterDatasetClass()
idFrd.Init(identityFunction, inputRasterDataset)
' Create a raster info function dataset.
Dim rasterInfoFunction As IRasterFunction = New RasterInfoFunctionClass()
Dim rasterInfoFuncArgs As IRasterInfoFunctionArguments = New RasterInfoFunctionArgumentsClass()
rasterInfoFuncArgs.Raster = inputRasterDataset
rasterInfoFuncArgs.RasterInfo = idFrd.RasterInfo
intermedFrd = New FunctionRasterDatasetClass()
intermedFrd.Init(rasterInfoFunction, rasterInfoFuncArgs)
Else
Return Nothing
End If
' Check if there is an RPC file associated with the image. If so
' then add a geometric function to apply the rpc xform.
If File.Exists(rpcPath) Then
opFrd = ApplyRPC(rpcPath, DirectCast(intermedFrd, IRasterDataset))
End If
' If no rpc pars exist or applying rpc fails, use the intermediate
' function raster dataset created.
If opFrd Is Nothing Then
opFrd = intermedFrd
'IRasterFunction ebFunction = new ExtractBandFunctionClass();
'IRasterFunctionArguments ebFuncArgs = new ExtractBandFunctionArgumentsClass();
'ILongArray bandIDs = new LongArrayClass();
'bandIDs.Add(2);
'bandIDs.Add(1);
'bandIDs.Add(0);
'''/bandIDs.Add(4);
'((IExtractBandFunctionArguments)ebFuncArgs).BandIDs = bandIDs;
'((IExtractBandFunctionArguments)ebFuncArgs).Raster = inputRasterDataset;
'opFrd = new FunctionRasterDatasetClass();
'opFrd.Init(ebFunction, ebFuncArgs);
'if (opFrd == null)
'{
' IRasterFunction identityFunction = new IdentityFunctionClass();
' opFrd = new FunctionRasterDatasetClass();
' opFrd.Init(identityFunction, inputRasterDataset);
'}
End If
Catch exc As Exception
Dim [error] As String = exc.Message
End Try
Return opFrd
End Function
''' <summary>
''' Parse the RPC parameters file associated with the image and create an RPCXform
''' to bea applied to the inputDataset as a geomtric function.
''' </summary>
''' <param name="rpcPath">Path to the rpc parameters file.</param>
''' <param name="inputDataset">Input dataset to apply the xform on.</param>
''' <returns>Function raster dataset created.</returns>
Private Function ApplyRPC(rpcPath As String, inputDataset As IRasterDataset) As IFunctionRasterDataset
Dim opFrd As IFunctionRasterDataset = Nothing
Try
' Open the RPC file and create Geometric transform
Dim finalXForm As IGeodataXform = Nothing
Dim rpcXForm As IRPCXform = GetRPCXForm(rpcPath)
Dim idFrd As IFunctionRasterDataset = Nothing
If Not (TypeOf inputDataset Is IFunctionRasterDataset) Then
Dim identityFunction As IRasterFunction = New IdentityFunctionClass()
idFrd = New FunctionRasterDatasetClass()
idFrd.Init(identityFunction, inputDataset)
Else
idFrd = DirectCast(inputDataset, IFunctionRasterDataset)
End If
Dim datasetRasterInfo As IRasterInfo = idFrd.RasterInfo
Dim datasetExtent As IEnvelope = datasetRasterInfo.Extent
Dim datasetSrs As ISpatialReference = DirectCast(idFrd, IGeoDataset).SpatialReference
Dim dRows As Long = datasetRasterInfo.Height
Dim dCols As Long = datasetRasterInfo.Width
Dim pixelExtent As IEnvelope = New EnvelopeClass()
pixelExtent.PutCoords(-0.5, 0.5 - dRows, -0.5 + dCols, 0.5)
Dim noAffineNeeded As Boolean = DirectCast(pixelExtent, IClone).IsEqual(DirectCast(datasetExtent, IClone))
If Not noAffineNeeded Then
' Tranform ground space to pixel space.
Dim affineXform As IAffineTransformation2D = New AffineTransformation2DClass()
affineXform.DefineFromEnvelopes(datasetExtent, pixelExtent)
Dim geoXform As IGeometricXform = New GeometricXformClass()
geoXform.Transformation = affineXform
finalXForm = geoXform
End If
' Transform from pixel space back to ground space to set as the forward transform.
Dim groundExtent As IEnvelope = DirectCast(idFrd, IGeoDataset).Extent
groundExtent.Project(datasetSrs)
Dim affineXform2 As IAffineTransformation2D = New AffineTransformation2DClass()
affineXform2.DefineFromEnvelopes(pixelExtent, groundExtent)
Dim forwardXForm As IGeometricXform = New GeometricXformClass()
forwardXForm.Transformation = affineXform2
rpcXForm.ForwardXform = forwardXForm
' Create the composite transform that changes ground values to pixel space
' then applies the rpc transform which will transform them back to ground space.
Dim compositeXForm As ICompositeXform = New CompositeXformClass()
compositeXForm.Add(finalXForm)
compositeXForm.Add(rpcXForm)
finalXForm = DirectCast(compositeXForm, IGeodataXform)
' Then apply the transform on the raster using the geometric function.
If finalXForm IsNot Nothing Then
Dim geometricFunction As IRasterFunction = New GeometricFunctionClass()
Dim geometricFunctionArgs As IGeometricFunctionArguments = Nothing
' Get the geomtric function arguments if supplied by the user (in the UI).
If myRasterTypeOperation IsNot Nothing AndAlso DirectCast(myRasterTypeOperation, IRasterTypeProperties).OrthorectificationParameters IsNot Nothing Then
geometricFunctionArgs = DirectCast(myRasterTypeOperation, IRasterTypeProperties).OrthorectificationParameters
Else
geometricFunctionArgs = New GeometricFunctionArgumentsClass()
End If
' Append the xform to the existing ones from the image.
geometricFunctionArgs.AppendGeodataXform = True
geometricFunctionArgs.GeodataXform = finalXForm
geometricFunctionArgs.Raster = inputDataset
opFrd = New FunctionRasterDatasetClass()
opFrd.Init(geometricFunction, geometricFunctionArgs)
End If
Return opFrd
Catch exc As Exception
Dim [error] As String = exc.Message
Return opFrd
End Try
End Function
''' <summary>
''' Create an RPCXForm from a text file containing parameters.
''' </summary>
''' <param name="rpcFilePath">Text file containing the parameters.</param>
''' <returns>The RPCXForm generated.</returns>
Private Function GetRPCXForm(rpcFilePath As String) As IRPCXform
Try
' Array for parameters.
Dim RPC As Double() = New Double(89) {}
' Propertyset to store properties as backup.
'IPropertySet coefficients = new PropertySetClass();
'#Region "Parse RPC text file"
' Use the stream reader to open the file and read lines from it.
Using sr As New StreamReader(rpcFilePath)
Dim line As String = ""
Dim lineNumber As Integer = 0
While (InlineAssignHelper(line, sr.ReadLine())) IsNot Nothing
lineNumber += 1
Try
' Split the line into tokens based on delimiters
Dim delimiters As Char() = {":"C, " "C}
Dim tokens As String() = line.Split(delimiters, System.StringSplitOptions.RemoveEmptyEntries)
Dim numTokens As Integer = tokens.GetLength(0)
If numTokens > 1 Then
Dim currPar As String = tokens(0)
Dim currValue As Double = Convert.ToDouble(tokens(1))
' Convert the Value to a double and store in the array.
' Store the property and the value in the propertyset to lookup later if needed.
'coefficients.SetProperty(currPar, currValue);
' Read units for conversion if needed
'string currUnit = tokens[2];
RPC((lineNumber - 1)) = currValue
Else
Console.WriteLine("Could not parse line " & lineNumber.ToString())
End If
Catch ex As Exception
Console.Write(ex.ToString())
End Try
End While
sr.Close()
End Using
'#End Region
' Create the new RPCXForm from the parameter array.
Dim myRPCXform As IRPCXform = DirectCast(New RPCXform(), IRPCXform)
Dim rpcCoeffs As Object = DirectCast(RPC, Object)
myRPCXform.DefineFromCoefficients(rpcCoeffs)
Return myRPCXform
Catch exc As Exception
Dim [error] As String = exc.Message
Throw exc
End Try
End Function
''' <summary>
''' Create new fields to add to the mosaic dataset attribute table.
''' </summary>
''' <param name="myFields">Fields to be added.</param>
Private Sub AddFields(myFields As IFields)
' Create a new field object
Dim pField As IField = New FieldClass()
' Set the field editor for this field
Dim objectIDFieldEditor As IFieldEdit = DirectCast(pField, IFieldEdit)
' Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SensorName"
objectIDFieldEditor.AliasName_2 = "Sensor Name"
' Set the type of the field
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeString
' Add the newly created field to list of existing fields
Dim fieldsEditor As IFieldsEdit = DirectCast(myFields, IFieldsEdit)
fieldsEditor.AddField(pField)
' Create a new field object
pField = New FieldClass()
' Set the field editor for this field
objectIDFieldEditor = DirectCast(pField, IFieldEdit)
' Set the name and alias of the field
objectIDFieldEditor.Name_2 = "AcquisitionDate"
objectIDFieldEditor.AliasName_2 = "Acquisition Date"
' Set the type of the field
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDate
fieldsEditor.AddField(pField)
' Create a new field object
pField = New FieldClass()
' Set the field editor for this field
objectIDFieldEditor = DirectCast(pField, IFieldEdit)
' Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SunAzimuth"
objectIDFieldEditor.AliasName_2 = "Sun Azimuth"
' Set the type of the field
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDouble
fieldsEditor.AddField(pField)
' Create a new field object
pField = New FieldClass()
' Set the field editor for this field
objectIDFieldEditor = DirectCast(pField, IFieldEdit)
' Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SunElevation"
objectIDFieldEditor.AliasName_2 = "Sun Elevation"
' Set the type of the field
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDouble
fieldsEditor.AddField(pField)
' Create a new field object
pField = New FieldClass()
' Set the field editor for this field
objectIDFieldEditor = DirectCast(pField, IFieldEdit)
' Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SatAzimuth"
objectIDFieldEditor.AliasName_2 = "Satellite Azimuth"
' Set the type of the field as Blob
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDouble
fieldsEditor.AddField(pField)
' Create a new field object
pField = New FieldClass()
' Set the field editor for this field
objectIDFieldEditor = DirectCast(pField, IFieldEdit)
' Set the name and alias of the field
objectIDFieldEditor.Name_2 = "SatElevation"
objectIDFieldEditor.AliasName_2 = "Satellite Elevation"
' Set the type of the field as Blob
objectIDFieldEditor.Type_2 = esriFieldType.esriFieldTypeDouble
fieldsEditor.AddField(pField)
End Sub
#End Region
#Region "IRasterBuilderInit Members"
Public Property DefaultSpatialReference() As ISpatialReference Implements IRasterBuilderInit.DefaultSpatialReference, IRasterBuilderInit2.DefaultSpatialReference
Get
Return myDefaultSpatialReference
End Get
Set
myDefaultSpatialReference = value
End Set
End Property
Public Property MosaicDataset() As IMosaicDataset Implements IRasterBuilderInit.MosaicDataset, IRasterBuilderInit2.MosaicDataset
Get
Return myMosaicDataset
End Get
Set
myMosaicDataset = value
End Set
End Property
Public Property RasterTypeOperation() As IRasterTypeOperation Implements IRasterBuilderInit.RasterTypeOperation, IRasterBuilderInit2.RasterTypeOperation
Get
Return myRasterTypeOperation
End Get
Set
myRasterTypeOperation = value
End Set
End Property
Public Property TrackCancel() As ITrackCancel Implements IRasterBuilderInit.TrackCancel, IRasterBuilderInit2.TrackCancel
Get
Return myTrackCancel
End Get
Set
myTrackCancel = value
End Set
End Property
#End Region
#Region "IPersistVariant Members"
''' <summary>
''' UID for the object implementing the Persist Variant
''' </summary>
Public ReadOnly Property ID() As UID Implements IPersistVariant.ID
Get
Return myUID
End Get
End Property
''' <summary>
''' Load the object from the stream provided
''' </summary>
''' <param name="Stream">Stream that represents the serialized Raster Type</param>
Public Sub Load(Stream As IVariantStream) Implements IPersistVariant.Load
Dim name As String = DirectCast(Stream.Read(), String)
'if (innerRasterBuilder is IPersistVariant)
' ((IPersistVariant)innerRasterBuilder).Load(Stream);
'innerRasterBuilder = (IRasterBuilder)Stream.Read(); // Load the innerRasterBuilder from the stream.
End Sub
''' <summary>
''' Same the Raster Type to the stream provided
''' </summary>
''' <param name="Stream">Stream to serialize the Raster Type into</param>
Public Sub Save(Stream As IVariantStream) Implements IPersistVariant.Save
Stream.Write("CustomRasterType")
'if (innerRasterBuilder is IPersistVariant)
' ((IPersistVariant)innerRasterBuilder).Save(Stream);
'Stream.Write(innerRasterBuilder); // Save the innerRasterBuilder into the stream.
End Sub
#End Region
#Region "IRasterBuilder2 Members"
''' <summary>
''' Check if the data source provided is a valid data source for the builder.
''' </summary>
''' <param name="vtDataSource">Data source (usually the path to a metadta file)</param>
''' <returns>Flag to specify whether it is valid source.</returns>
Public Function CanBuild(vtDataSource As Object) As Boolean Implements IRasterBuilder2.CanBuild
If Not (TypeOf vtDataSource Is String) Then
Return False
End If
Dim dimFilePath As String = DirectCast(vtDataSource, String)
If Not dimFilePath.ToLower().EndsWith(".dim") Then
Return False
End If
Dim myDimParser As DiMapParser = Nothing
Try
myDimParser = New DiMapParser(dimFilePath)
If myDimParser.MetadataProfile.ToLower() = "DMCII".ToLower() Then
myDimParser = Nothing
Return True
Else
myDimParser = Nothing
Return False
End If
Catch exc As Exception
myDimParser = Nothing
Dim [error] As String = exc.Message
Return False
End Try
End Function
Public ReadOnly Property CanMergeItems() As Boolean Implements IRasterBuilder2.CanMergeItems
Get
Return myCanMergeItems
End Get
End Property
Public Property MergeItems() As Boolean Implements IRasterBuilder2.MergeItems
Get
Return myMergeItems
End Get
Set
myMergeItems = value
End Set
End Property
''' <summary>
''' Check to see if the properties provided to the raster type/builder
''' are sufficient for it to work. Usually used for UI validation.
''' </summary>
Public Sub Validate() Implements IRasterBuilder2.Validate
Return
End Sub
#End Region
#Region "IRasterBuilderInit2 Members"
''' <summary>
''' Helper object to store geographic transformations set on the mosaic dataset.
''' </summary>
Public Property GeoTransformationHelper() As IGeoTransformationHelper Implements IRasterBuilderInit2.GeoTransformationHelper
Get
Return myGeoTransformationHelper
End Get
Set
myGeoTransformationHelper = Nothing
End Set
End Property
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
#End Region
End Class
''' <summary>
''' Class used to parse the dim file (xml format) and get relevant properties from it.
''' </summary>
Public Class DiMapParser
Private myXmlPath As String
Private myXmlDoc As XmlDocument
Private bandInfo As XmlNodeList
Private bandStats As XmlNodeList
Private footprintInfo As XmlNodeList
Private vertexCount As Integer
Public Sub New()
myXmlPath = Nothing
bandInfo = Nothing
bandStats = Nothing
footprintInfo = Nothing
vertexCount = 0
End Sub
Public Sub New(xmlPath As String)
myXmlPath = xmlPath
bandInfo = Nothing
bandStats = Nothing
footprintInfo = Nothing
vertexCount = 0
myXmlDoc = New XmlDocument()
myXmlDoc.Load(myXmlPath)
End Sub
''' <summary>
''' Flag to specify whether the footprint exists in the xml file.
''' </summary>
Public ReadOnly Property FootPrintExists() As Boolean
Get
If footprintInfo Is Nothing Then
footprintInfo = myXmlDoc.SelectSingleNode("//Dataset_Frame").SelectNodes("Vertex")
End If
Return footprintInfo IsNot Nothing
End Get
End Property
''' <summary>
''' Reset the vertex count to get vertices of the footprint.
''' </summary>
Public Sub ResetVertexCount()
vertexCount = 0
End Sub
Public Function GetNextVertex(ByRef x As String, ByRef y As String, ByRef col As String, ByRef row As String) As Boolean
If footprintInfo Is Nothing Then
footprintInfo = myXmlDoc.SelectSingleNode("//Dataset_Frame").SelectNodes("Vertex")
End If
x = footprintInfo(vertexCount).SelectSingleNode("FRAME_LON").InnerText
y = footprintInfo(vertexCount).SelectSingleNode("FRAME_LAT").InnerText
col = footprintInfo(vertexCount).SelectSingleNode("FRAME_COL").InnerText
row = footprintInfo(vertexCount).SelectSingleNode("FRAME_ROW").InnerText
vertexCount += 1
If vertexCount >= footprintInfo.Count Then
Return False
Else
Return True
End If
End Function
''' <summary>
''' Get next vertex from the footprint defined in the xml based on the vertex count and unit.
''' </summary>
''' <param name="x">The X value.</param>
''' <param name="y">The Y value.</param>
''' <param name="unit">Unit to check which parameter to get vertex from.</param>
''' <returns>True if next vertex exists.</returns>
Public Function GetNextVertex2(ByRef x As String, ByRef y As String, unit As String) As Boolean
If unit = "Deg" Then
If footprintInfo Is Nothing Then
footprintInfo = myXmlDoc.SelectSingleNode("//Dataset_Frame").SelectNodes("Vertex")
End If
x = footprintInfo(vertexCount).SelectSingleNode("FRAME_LON").InnerText
'col = footprintInfo[vertexCount].SelectSingleNode("FRAME_COL").InnerText;
'row = footprintInfo[vertexCount].SelectSingleNode("FRAME_ROW").InnerText;
y = footprintInfo(vertexCount).SelectSingleNode("FRAME_LAT").InnerText
Else
If footprintInfo Is Nothing Then
footprintInfo = myXmlDoc.SelectSingleNode("//Dataset_Frame").SelectNodes("Vertex")
End If
x = footprintInfo(vertexCount).SelectSingleNode("FRAME_X").InnerText
'col = footprintInfo[vertexCount].SelectSingleNode("FRAME_COL").InnerText;
'row = footprintInfo[vertexCount].SelectSingleNode("FRAME_ROW").InnerText;
y = footprintInfo(vertexCount).SelectSingleNode("FRAME_Y").InnerText
End If
vertexCount += 1
If vertexCount >= footprintInfo.Count Then
Return False
Else
Return True
End If
End Function
''' <summary>
''' The number of bands defined in the xml.
''' </summary>
Public ReadOnly Property NumBands() As Integer
Get
If bandInfo Is Nothing Then
bandInfo = myXmlDoc.SelectNodes("//Spectral_Band_Info")
End If
If bandStats Is Nothing Then
bandStats = myXmlDoc.SelectNodes("//Band_Statistics")
End If
Return bandInfo.Count
End Get
End Property
''' <summary>
''' Index of the band based on the counter.
''' </summary>
''' <param name="indexCounter">Counter (similar to vertexCount) to get the index for.</param>
''' <returns>Index of the band as string.</returns>
Public Function GetBandIndex(indexCounter As Integer) As String
If bandInfo Is Nothing Then
bandInfo = myXmlDoc.SelectNodes("//Spectral_Band_Info")
End If
Return bandInfo(indexCounter).SelectSingleNode("BAND_INDEX").InnerText
End Function
''' <summary>
''' Get the name of the band.
''' </summary>
''' <param name="bandIndex">Index of the band for which to get the name.</param>
''' <returns>Band name as string.</returns>
Public Function GetBandDesc(bandIndex As Integer) As String
If bandInfo Is Nothing Then
bandInfo = myXmlDoc.SelectNodes("//Spectral_Band_Info")
End If
Return bandInfo(bandIndex - 1).SelectSingleNode("BAND_DESCRIPTION").InnerText
End Function
''' <summary>
''' Get minimum value for the band.
''' </summary>
''' <param name="bandIndex">Index of the band for which to get the value.</param>
''' <returns>Value requested as string.</returns>
Public Function GetBandStatMin(bandIndex As Integer) As String
If bandStats Is Nothing Then
bandStats = myXmlDoc.SelectNodes("//Band_Statistics")
End If
Return bandStats(bandIndex - 1).SelectSingleNode("STX_LIN_MIN").InnerText
End Function
''' <summary>
''' Get maximum value for the band.
''' </summary>
''' <param name="bandIndex">Index of the band for which to get the value.</param>
''' <returns>Value requested as string.</returns>
Public Function GetBandStatMax(bandIndex As Integer) As String
If bandStats Is Nothing Then
bandStats = myXmlDoc.SelectNodes("//Band_Statistics")
End If
Return bandStats(bandIndex - 1).SelectSingleNode("STX_LIN_MAX").InnerText
End Function
''' <summary>
''' Get mean value for the band.
''' </summary>
''' <param name="bandIndex">Index of the band for which to get the value.</param>
''' <returns>Value requested as string.</returns>
Public Function GetBandStatMean(bandIndex As Integer) As String
If bandStats Is Nothing Then
bandStats = myXmlDoc.SelectNodes("//Band_Statistics")
End If
Return bandStats(bandIndex - 1).SelectSingleNode("STX_MEAN").InnerText
End Function
''' <summary>
''' Get standard deviation value for the band.
''' </summary>
''' <param name="bandIndex">Index of the band for which to get the value.</param>
''' <returns>Value requested as string.</returns>
Public Function GetBandStatStdDev(bandIndex As Integer) As String
If bandStats Is Nothing Then
bandStats = myXmlDoc.SelectNodes("//Band_Statistics")
End If
Return bandStats(bandIndex - 1).SelectSingleNode("STX_STDV").InnerText
End Function
''' <summary>
''' Get the product type for the dataset.
''' </summary>
Public ReadOnly Property ProductType() As String
Get
Return myXmlDoc.SelectSingleNode("//PRODUCT_TYPE").InnerText
End Get
End Property
''' <summary>
''' Get the sensor name for the dataset.
''' </summary>
Public ReadOnly Property MetadataProfile() As String
Get
Return myXmlDoc.SelectSingleNode("//METADATA_PROFILE").InnerText
End Get
End Property
''' <summary>
''' Get the geometric processing for the dataset.
''' </summary>
Public ReadOnly Property GeometricProcessing() As String
Get
Return myXmlDoc.SelectSingleNode("//GEOMETRIC_PROCESSING").InnerText
End Get
End Property
''' <summary>
''' Get the Acquisition Date for the dataset.
''' </summary>
Public ReadOnly Property AcquisitionDate() As String
Get
Return myXmlDoc.SelectSingleNode("//IMAGING_DATE").InnerText
End Get
End Property
''' <summary>
''' Get the Acquisition Time for the dataset.
''' </summary>
Public ReadOnly Property AcquisitionTime() As String
Get
Return myXmlDoc.SelectSingleNode("//IMAGING_TIME").InnerText
End Get
End Property
''' <summary>
''' Get the Sensor Angle for the dataset.
''' </summary>
Public ReadOnly Property IncidenceAngle() As String
Get
Return myXmlDoc.SelectSingleNode("//INCIDENCE_ANGLE").InnerText
End Get
End Property
''' <summary>
''' Get the Sun Azimuth for the dataset.
''' </summary>
Public ReadOnly Property SunAzimuth() As String
Get
Return myXmlDoc.SelectSingleNode("//SUN_AZIMUTH").InnerText
End Get
End Property
''' <summary>
''' Get the Sun Elevation for the dataset.
''' </summary>
Public ReadOnly Property SunElevation() As String
Get
Return myXmlDoc.SelectSingleNode("//SUN_ELEVATION").InnerText
End Get
End Property
''' <summary>
''' Get the epsg code for the spatial reference of the dataset.
''' </summary>
Public ReadOnly Property SrsCode() As String
Get
Return myXmlDoc.SelectSingleNode("//HORIZONTAL_CS_CODE").InnerText
End Get
End Property
''' <summary>
''' Get the Sensor Azimuth for the dataset.
''' </summary>
Public ReadOnly Property SensorAzimuth() As String
Get
Dim qualityAssessments As XmlNodeList = myXmlDoc.SelectNodes("//Quality_Assessment")
Dim qualityPars As XmlNodeList = qualityAssessments(1).SelectNodes("Quality_Parameter")
For i As Integer = 0 To qualityPars.Count - 1
If qualityPars(i).SelectSingleNode("QUALITY_PARAMETER_CODE").InnerText.Contains("SENSOR_AZIMUTH") Then
Return qualityPars(i).SelectSingleNode("QUALITY_PARAMETER_VALUE").InnerText
End If
Next
Return ""
End Get
End Property
End Class