using System;
using System.Drawing;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.GlobeCore;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Analyst3D;
using System.Windows.Forms;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.SystemUI;
namespace TestDrapeApplication
{
/// <summary>
/// Command that works in ArcGlobe or GlobeControl
/// </summary>
[Guid("2d4a8248-b8d1-459f-aa4d-c73fdd4cde3b")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("TestDrapeApplication.AddShapeFileMemory")]
public sealed class AddShapeFileMemory : BaseCommand
{
#region COM Registration Function(s)
[ComRegisterFunction()]
[ComVisible(false)]
static void RegisterFunction(Type registerType)
{
// Required for ArcGIS Component Category Registrar support
ArcGISCategoryRegistration(registerType);
//
// TODO: Add any COM registration code here
//
}
[ComUnregisterFunction()]
[ComVisible(false)]
static void UnregisterFunction(Type registerType)
{
// Required for ArcGIS Component Category Registrar support
ArcGISCategoryUnregistration(registerType);
//
// TODO: Add any COM unregistration code here
//
}
#region ArcGIS Component Category Registrar generated code
/// <summary>
/// Required method for ArcGIS Component Category registration -
/// Do not modify the contents of this method with the code editor.
/// </summary>
private static void ArcGISCategoryRegistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
GMxCommands.Register(regKey);
ControlsCommands.Register(regKey);
}
/// <summary>
/// Required method for ArcGIS Component Category unregistration -
/// Do not modify the contents of this method with the code editor.
/// </summary>
private static void ArcGISCategoryUnregistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
GMxCommands.Unregister(regKey);
ControlsCommands.Unregister(regKey);
}
#endregion
#endregion
private IGlobeHookHelper m_globeHookHelper = null;
public AddShapeFileMemory()
{
//
// TODO: Define values for the public properties
//
base.m_category = "Add Shape File to map"; //localizable text
base.m_caption = "Add Shape File"; //localizable text
base.m_message = "Add shape File to Map"; //localizable text
base.m_toolTip = "Add Shape File to Map"; //localizable text
base.m_name = "AddShapeFileMemory"; //unique id, non-localizable (e.g. "MyCategory_MyCommand")
try
{
//
// TODO: change bitmap name if necessary
//
string bitmapResourceName = GetType().Name + ".bmp";
base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
}
}
#region Overriden Class Methods
/// <summary>
/// Occurs when this command is created
/// </summary>
/// <param name="hook">Instance of the application</param>
public override void OnCreate(object hook)
{
if (hook == null)
return;
try
{
m_globeHookHelper = new GlobeHookHelperClass();
m_globeHookHelper.Hook = hook;
if (m_globeHookHelper.ActiveViewer == null)
{
m_globeHookHelper = null;
}
}
catch
{
m_globeHookHelper = null;
}
if (m_globeHookHelper == null)
base.m_enabled = false;
else
base.m_enabled = true;
// TODO: Add other initialization code
}
/// <summary>
/// Occurs when this command is clicked
/// </summary>
public override void OnClick()
{
//This is run after adding document with elevation Raster layer
IGlobeDisplay globeDisplay = new GlobeDisplayClass();
globeDisplay = m_globeHookHelper.GlobeDisplay;
double lon = -86.00;
double lat = 37.9166;
double alt = 100.0;
double azimuth = 175.0;
double range = 1000; //ConvertMetersToDatasetUnits((IGlobe2)globeDisplay.Globe, 1000.0);
double fov = 60.0;
m_globeHookHelper.GlobeDisplay.RefreshViewers();
//Elevation present to here.
AddElement(ref globeDisplay, azimuth, fov, range, lat, lon, alt);
// still have elevation with polygon under elevated layer.
m_globeHookHelper.GlobeDisplay.RefreshViewers();
}
#endregion
private void AddElement(ref IGlobeDisplay globeDisplay, double azimuth, double fov, double range, double lat, double lon, double alt)
{
//Depending on the ASCII file type set a variable which will control the flow of the application
string shapeType = null;
string sensorID = "Sim.Trip1";
//shapeType = "points";
// shapeType = "polylines";
shapeType = "polygons";
string datasetType = "Shapefile";
IWorkspace workSpace = null;
workSpace = this.CreateWorkspace();
IFields fields = CreateFields(shapeType);
//Create the Feature Class
IFeatureClass featureClass = CreateFeatureClass(workSpace, null, shapeType, fields, null, null, "");
AddShape(ref featureClass, ref workSpace, azimuth, fov, range, lat, lon, alt, sensorID);
//Create a Feature Layer to display the data in ArcMap
IFeatureLayer featureLayer = new FeatureLayerClass();
featureLayer.FeatureClass = featureClass;
featureLayer.Name = featureClass.AliasName;
featureLayer.Visible = true;
IGeoFeatureLayer lyr = (IGeoFeatureLayer)featureLayer;
IRgbColor lyrColor = new RgbColorClass();
lyrColor.Red = 255;
lyrColor.Green = 0;
lyrColor.Blue = 0;
ISimpleFillSymbol sfSymbol = new SimpleFillSymbolClass();
sfSymbol.Color = lyrColor;
sfSymbol.Outline.Width = 0.4;
sfSymbol.Style = esriSimpleFillStyle.esriSFSSolid;
ISimpleRenderer lyrSimRend = new SimpleRendererClass();
lyrSimRend.Symbol = (ISymbol)sfSymbol;
lyr.Renderer = (IFeatureRenderer)lyrSimRend;
((IScene)globeDisplay.Globe).AddLayer(featureLayer, true);
ILayer lyrCreated = featureLayer;
((IActiveView)globeDisplay.Globe).Extent = lyrCreated.AreaOfInterest;
}
private IWorkspace CreateWorkspace()
{
try
{
IWorkspaceFactory workspaceFactory = null;
// Instantiate a Shapefile workspace factory
//workspaceFactory = new ShapefileWorkspaceFactoryClass();
Type factoryType = Type.GetTypeFromProgID("esriDataSourcesFile.ShapefileWorkspaceFactory");
workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
//Create a directory hierarchy to seperate out datasets created for Points, Polylines, and Polygons
IWorkspaceName workspaceName = workspaceFactory.Create(Application.StartupPath + @"\ShapeFile", "Shapefile", null, 0);
IName Name = (IName)workspaceName;
IWorkspace workspace = (IWorkspace)(Name.Open());
return workspace;
}
catch (Exception ex)
{
String mess = ex.Message;
MessageBox.Show(mess);
return null;
}
}
private IFields CreateFields(string shapeType)
{
// Create a new fields collection.
IFields fields = new FieldsClass();
// Cast to IFieldsEdit to modify the properties of the fields collection.
IFieldsEdit fieldsEdit = (IFieldsEdit)fields;
// Set the number of fields the collection will contain.
fieldsEdit.FieldCount_2 = 5;
// Create the ObjectID field.
IField oidField = new FieldClass();
IFieldEdit oidFieldEdit = (IFieldEdit)oidField;
oidFieldEdit.Name_2 = "ObjectID";
oidFieldEdit.AliasName_2 = "FID";
oidFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID;
fieldsEdit.set_Field(0, oidField);
// Create the myID field.
IField myIDField = new FieldClass();
IFieldEdit myIDFieldEdit = (IFieldEdit)myIDField;
myIDFieldEdit.Name_2 = "SensorID";
myIDFieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
fieldsEdit.set_Field(1, myIDField);
// Create the text field.
IField textField = new FieldClass();
IFieldEdit textFieldEdit = (IFieldEdit)textField;
textFieldEdit.Length_2 = 30; // Only string fields require that you set the length.
textFieldEdit.Name_2 = "Str_Att1";
textFieldEdit.Type_2 = esriFieldType.esriFieldTypeString;
fieldsEdit.set_Field(2, textField);
// Create the numeric field.
IField numericField = new FieldClass();
IFieldEdit numericFieldEdit = (IFieldEdit)numericField;
numericFieldEdit.Name_2 = "Num_Att1";
numericFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;
fieldsEdit.set_Field(3, numericField);
//Create the SHAPE field.
IField shapeField = new FieldClass();
IFieldEdit shapeFieldEdit = (IFieldEdit)shapeField;
shapeFieldEdit.Name_2 = "SHAPE";
shapeFieldEdit.IsNullable_2 = true;
shapeFieldEdit.Required_2 = true;
IGeometryDef geometryDef = new GeometryDefClass();
IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;
geometryDefEdit.AvgNumPoints_2 = 1;
geometryDefEdit.GridCount_2 = 0;
geometryDefEdit.HasM_2 = false;
geometryDefEdit.HasZ_2 = false;
//Depending on the feature type (ie. Point, Polyline, or Polygon)
//set the appropriate .Type_2 and .GeometryType_2 Properties.
if (shapeType == "points")
{
shapeFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;
}
else if (shapeType == "polylines")
{
shapeFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolyline;
}
else if (shapeType == "polygons")
{
shapeFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
geometryDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon;
}
//Generate a default Spatial Reference
ISpatialReference spatialReference = MakeSpatialReference(esriSRProjCSType.esriSRProjCS_Sphere_AzimuthalEquidistant);
geometryDefEdit.SpatialReference_2 = spatialReference;
shapeFieldEdit.GeometryDef_2 = (GeometryDef)geometryDefEdit;
fieldsEdit.set_Field(4, shapeFieldEdit);
return fields;
}
///<summary>Helper to create a Feature Class.</summary>
public IFeatureClass CreateFeatureClass(IWorkspace workspace, IFeatureDataset featureDataset, System.String featureClassName, IFields fields, ESRI.ArcGIS.esriSystem.UID CLSID, ESRI.ArcGIS.esriSystem.UID CLSEXT, System.String strConfigKeyword)
{
if (featureClassName == "")
{
return null; // name was not passed in
}
featureClassName = "newShapeFile";
IFeatureClass featureClass = null;
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace; // Explicit Cast
// assign the class id value if not assigned
if (CLSID == null)
{
CLSID = new ESRI.ArcGIS.esriSystem.UIDClass();
CLSID.Value = "esriGeoDatabase.Feature";
}
System.String strShapeField = "";
// locate the shape field
//for (Int32 j = 0; j < fields.FieldCount; j++)
//{
// if (fields.get_Field(j).Type == esriFieldType.esriFieldTypeGeometry)
// {
// strShapeField = fields.get_Field(j).Name;
// }
//}
strShapeField = "SHAPE";
// finally create and return the feature class
// no feature dataset passed in, create at the workspace level
try
{
featureClass = featureWorkspace.CreateFeatureClass(featureClassName, fields, CLSID, CLSEXT, esriFeatureType.esriFTSimple, strShapeField, strConfigKeyword);
}
catch (Exception ex)
{
String mess = ex.Message;
MessageBox.Show(mess);
}
return featureClass;
}
public ISpatialReference MakeSpatialReference(esriSRProjCSType coordinateSystem)
{
ISpatialReferenceFactory spatialReferenceFactory = new SpatialReferenceEnvironmentClass();
//Create a projected coordinate system and define its domain, resolution, and x,y tolerance.
ISpatialReferenceResolution spatialReferenceResolution = spatialReferenceFactory.CreateProjectedCoordinateSystem(System.Convert.ToInt32(coordinateSystem)) as ISpatialReferenceResolution;
spatialReferenceResolution.ConstructFromHorizon();
ISpatialReferenceTolerance spatialReferenceTolerance = spatialReferenceResolution as ISpatialReferenceTolerance;
spatialReferenceTolerance.SetDefaultXYTolerance();
ISpatialReference spatialReference = spatialReferenceResolution as ISpatialReference;
return spatialReference;
}
private void AddShape(ref IFeatureClass FeatureClass, ref IWorkspace workspace, double azimuth, double fov, double range, double lat, double lon, double alt, String sensorID)
{
// Start an edit session and edit operation.
IWorkspaceEdit workspaceEdit = (IWorkspaceEdit)workspace;
workspaceEdit.StartEditing(true);
workspaceEdit.StartEditOperation();
int IDAttributeFieldIndex = FeatureClass.FindField("SensorID");
int StringAttributeFieldIndex = FeatureClass.FindField("Str_Att1");
int NumericAttributeFieldIndex = FeatureClass.FindField("Num_Att1");
ComReleaser comReleaser = new ComReleaser();
// Create a new insert cursor with buffering.
IFeatureCursor featureCursor = FeatureClass.Insert(true);
comReleaser.ManageLifetime(featureCursor);
// Create a feature buffer. This will store the values common to every
// feature to be installed.
IFeatureBuffer featureBuffer = FeatureClass.CreateFeatureBuffer();
comReleaser.ManageLifetime(featureBuffer);
IPolygon polygon = makePolygon(azimuth, fov, range, lat, lon, alt);
featureBuffer.Shape = (IGeometry)polygon;
featureBuffer.set_Value(IDAttributeFieldIndex, sensorID);
featureBuffer.set_Value(StringAttributeFieldIndex, "Try this");
featureBuffer.set_Value(IDAttributeFieldIndex, 2);
featureCursor.InsertFeature(featureBuffer);
// Flush the cursor.
featureCursor.Flush();
// All of the features were successfully inserted; stop the edit operation
// and stop the edit session, saving the changes made in edit operations.
workspaceEdit.StopEditOperation();
workspaceEdit.StopEditing(true);
}
#region "Build Polygon"
/// <summary>
/// Takes input of azimuth field of view and range with position and altitude
/// to make a circular arc polygon to add as a symbol for element in layer.
/// </summary>
/// <param name="azimuth"></param>
/// <param name="fov"></param>
/// <param name="range"></param>
/// <param name="lat"></param>
/// <param name="lon"></param>
/// <param name="alt"></param>
/// <returns>IPolygon polygon</returns>
private IPolygon makePolygon(double azimuth, double fov, double range, double lat, double lon, double alt)
{
object missing = System.Reflection.Missing.Value;
//IZAware zAware;
IPolygon polygon = new PolygonClass();
IPoint centerPoint = new PointClass();
IPoint startPoint = new PointClass();
IPoint endPoint = new PointClass();
Boolean isCCW = true;
Boolean isMinor = false;
centerPoint.SpatialReference = MakeSpatialReference(esriSRProjCSType.esriSRProjCS_Sphere_AzimuthalEquidistant);
startPoint.SpatialReference = centerPoint.SpatialReference;
endPoint.SpatialReference = centerPoint.SpatialReference;
//zAware = centerPoint as IZAware;
zAware.ZAware = true;
//zAware = startPoint as IZAware;
zAware.ZAware = true;
//zAware = endPoint as IZAware;
zAware.ZAware = true;
centerPoint.PutCoords(lon, lat);
centerPoint.Z = alt;
double Xray = centerPoint.X;
double Yankee = centerPoint.Y;
ICircularArc circularArc = new CircularArcClass();
ISegmentCollection ring1 = new RingClass();
ring1.AddSegment(circularArc as ISegment, ref missing, ref missing);
double fovRadian = 0.0;
fovRadian = (fov * 2 * Math.PI) / 360;
circularArc.PutCoordsByAngle(centerPoint, GetFromAngle(azimuth, fov), fovRadian, range);
circularArc.QueryCoords(centerPoint, startPoint, endPoint, ref isCCW, ref isMinor);
ILine lineOut = new LineClass();
ILine lineIn = new LineClass();
lineOut.PutCoords(centerPoint, startPoint);
lineIn.PutCoords(endPoint, centerPoint);
ISegmentCollection segColl = new PolygonClass();
segColl.AddSegment((ISegment)lineOut, ref missing, ref missing);
segColl.AddSegment((ISegment)circularArc, ref missing, ref missing);
segColl.AddSegment((ISegment)lineIn, ref missing, ref missing);
polygon = segColl as IPolygon;
//IGeometryCollection geometryCollection = polygon as IGeometryCollection;
//geometryCollection.AddGeometry(segColl as IGeometry, ref missing, ref missing);
//geometryCollection.GeometriesChanged();
return polygon;
}
/// <summary>
/// Converts Azimuth and Field of View width to geometric
/// start angle of circular arc.
/// </summary>
/// <param name="azimuth"></param>
/// <param name="FOV"></param>
/// <returns>Double startAngle</returns>
private double GetFromAngle(double azimuth, double FOV)
{
double startAngle = 0.0;
double fovRadian = 0.0;
fovRadian = (FOV * 2 * Math.PI) / 360;
startAngle = AzimuthToAngle(azimuth) - (.5 * fovRadian);
return startAngle;
}
/// <summary>
/// Converts Azimuth to geometric angle of arc.
/// </summary>
/// <param name="azimuth"></param>
/// <returns>double angle</returns>
private double AzimuthToAngle(double azimuth)
{
double angle = 0.0;
double angleRadian = 0.0;
angleRadian = (azimuth * 2 * Math.PI) / 360;
angle = (2 * Math.PI) - (angleRadian - Math.PI / 2);
if (angle >= 2 * Math.PI)
{
angle -= 2 * Math.PI;
}
return angle;
}
private double ConvertMetersToDatasetUnits(IGlobe2 globe, double meters)
{
try
{
esriUnits units = globe.GlobeUnits;
IUnitConverter cvtr = new UnitConverter();
double mapUnits = cvtr.ConvertUnits(meters, esriUnits.esriMeters, units);
return mapUnits;
}
catch (Exception ex)
{
String mess = ex.Message;
return -1.0;
}
}
#endregion
}
}