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 } }