Having trouble converting an Ilayer to an IPolygon.
I am developing a toolbar for ArcMap and I grab a layer via code from the side table of contents. The Layer is a Polygon, but the code won't convert it to a IPolygon.
Can anyone help me out? This is the code I am using to try and convert it to a IPolygon...
IPolygon poly = m_document.Maps.get_Item(0).get_Layer(0) as IPolygon;
I can do this:
ILayer layer = m_document.Maps.get_Item(0).get_Layer(0) as ILayer;
And that works, just not converting it to a IPloygon..
If you want to access the geometries contained in a shapefile layer, you have to get the layer's feature class. This is a property of the IFeatureLayer interface, so you'll have to cast your layer (which is an ILayer) first:
IFeatureLayer FLayer = layer as IFeatureLayer;
IFeatureClass FClass = FLayer.FeatureClass;
If you have a feature class, you can get features by index (slow) or by defining a cursor on the feature class (this is fast and the preferred way when you want to handle lots of features. Search for IFeatureCursor; ESRI docs usualy come with good code snippets).
If your feature class contains only one feature, or if you only want one feature, You can use the GetFeature method:
IFeature MyFeature = FClass.GetFeature(0);
Now you're almost there. A feature's geometry is tucked away in its Shape property:
IPolygon MyPoly = MyFeature.Shape as IPolygon;
The extra cast is needed because the Shape property is an IPolygon, which is a more specific IGeometry.
The ILayer will be made up of multiple polygons. Think of a layer as a sql table and a feature as a row in that table. The IPolygon will refer to the geometry that makes up an individual feature. You may need to cast that ILayer as something like an IFeatureLayer to get access to the right properties/methods to access the individual features within your layer.
Related
This is maybe something I know how to do or have already done it in the past. For some reason I am drawing a blank on how to wrap my head around it. This is more for learning as well as trying to implement something in my app.
I am using a set of third party controls. These controls offer a lot of functionality which is great. However, I want to be able to create a custom object that handle the logic/properties for the datasource of this control.
For example, there is a spreadsheet like object that I am using. You supply the spreadsheet like object some data and it pulls in your data. The problem here is that you need to set the columns, their data types, and other formatting/events as well as some logic to spit the data back to the user.
List<CustomClassWithProperties> dataSource
The custom class has some properties that will be translated to the columns. Like ProductName, Price, SalesDepartment, DatePurchased etc. This can be done by supplying the spreadsheet the columns and their data types each time. I want to be able to create a helper class that you just supply a list, a visible column list, and an editable column list and the data will fill in without any other issues.
Using the above list, I would imagine something similar to this:
DataHelperClass dtHlpr = new DataHelperClass(List<CustomClassWithProperties> data, List<string> visibleColumns, List<string> editableColumns)
This data helper class will take the data input list as the spreadsheet data source. It would then take the visibleColumns list and use that to set the visible rows, same for editableColumns.
Where I am running into a mental block (long week) is when I want to be able to reuse this. Let's say I have a List that has completely different properties. I would want my constructor for the data helper to be able to handle any List I send to it. Looking at whatever code I can get to for the third party controls, it appears that their data source is of type object.
Could someone point me in the right direction? I am thinking it has to do with generics and some interface implementation. I just honestly cannot think of where to start.
You can make the class itself generic:
public class DataHelperClass<T>
{
public DataHelperClass(List<T> data, ...) { ... }
}
DataHelperClass<CustomClassWithProperties> dtHlpr = new DataHelperClass<CustomClassWithProperties>(List<CustomClassWithProperties> data, List<string> visibleColumns, List<string> editableColumns)
You'd then perform your reflection against typeof(T).
I'd also be tempted to use IEnumerable<T> rather than List<T> if possible, but that's a matter of preference, more or less.
This is similar to using a simple List<object>, except that it enforces that all objects in the list inherit from the same type (which might well be object), so you get some more type-checking than you otherwise would.
You mentioned interfaces, I don't see any reason here to include that (from what you've told us, at least), but you can certainly make a generic interface via the same syntax.
From System.Data.Entity.SqlServer.SqlSpatialFunctions class definition:
Contains function stubs that expose SqlServer methods in Linq to Entities.
I know that Linq to Entities is mentioned specifically, however I was wondering if some functionality can be replicated in my back end code.
I've got an account Model, with lazy loaded collection of Polygons. Each Polygon contains a DbGeography type property called Location.
I'm trying to get all Polygons that interesct certain point (which also has lazy loaded property Address, which has DbGeography type property called Location).
I can do it like this:
var matchedPolygons =
account.Polygons.Where(
x =>
point.Address.Location.Intersects(x.Polygon.Location)).ToList();
which works fine.
In order to try to improve the performance, I thought it would be a good idea to slightly reduce the Polygon data.
var matchedPolygons =
account.Polygons.Where(
x =>
point.Address.Location.Intersects(SqlSpatialFunctions.Reduce(x.Polygon.Location, 100))).ToList();
This however throws the following System.NotSupportedException exception:
This function can only be invoked from LINQ to Entities.
I know I can retrieve the polygons directly from my repository layer using the Reduce method above, but since I'm using lazy loading and have Polygons collection available to me already, I thought there might be a way of using SqlSpatialFunctions at this stage.
The only thing I've ever been able to come up with a gross hack. It works, but I make no claim as to elegance.
Toss in these includes (make the references as well):
using System.Data.Entity.Spatial;
using System.Data.SqlTypes;
Convert the DbGeography to a SqlGeography:
Microsoft.SqlServer.Types.SqlGeography sqlGeography = Microsoft.SqlServer.Types.SqlGeography.STGeomFromWKB(new SqlBytes(geog.AsBinary()), mydbgeog.CoordinateSystemId);
Maybe it's okay if you keep it as SqlGeography, but if not convert it back.
sqlGeography = sqlGeography.Reduce(50);
mydbgeog = DbGeography.FromBinary(sqlGeography.STAsBinary().Value);
It's the fastest way I know of to toss back and forth between DbGeography and SqlGeography. Again, it's gross and requires an additional library to be in place but honestly there's a lot of stuff in SqlGeography that for a big GIS application will probably need.
I am developing a windows store app that allows a User to place points on a map and load them from a server. I have this working fine but I need to include more properties than the standard Pushpin class allows (rating / description / user).
Because Pushpin is sealed, I cannot add these fields and use my own object in place of Pushpin. I tried over the past couple of hours to compose my own PointOfInterest class with a Pushpin object inside it however, this approach fails in a number of areas (When I place a point on a map, I want to retrieve more details than just name / tag and have no way of getting a reference back to the original object.)
If anybody has an idea of where to go from here I would like to hear from you !
If you need access to the private members of a sealed class then you are out of luck.
Best you can do is proxy (which you already seem to be doing by including it as a member). Also called faking it :)
I have X layers on a map and I need to intersect chosen layers (two per time) and color resulting features.
I'm trying to get this code working
// get first feature (index 0)
ESRI.ArcGIS.ADF.Web.Geometry.Geometry adfFeature =
m_firstLayer.GeometryFromRow(m_firstLayer.Rows[0])
as ESRI.ArcGIS.ADF.Web.Geometry.Geometry;
// THE FOLLOWING LINE RETURNS NULL
ESRI.ArcGIS.Geometry.IGeometry featureInterface =
adfFeature as ESRI.ArcGIS.Geometry.IGeometry;
ESRI.ArcGIS.Geometry.ITopologicalOperator topoOp =
adfFeature as ESRI.ArcGIS.Geometry.ITopologicalOperator;
How to use the IGeometry interface with an ADF Geometry object?
I can't really find samples to intersect features between two layers, and it's a pity that Spatial Joins are just a arcgis desktop function, I surely could use them!
I do not think you use the IGeometry directly. However if you know the specialized type (Point, Polyline, Polygon) you can convert (see the "Web ADF to ArcGIS Server ArcObjects" bullets) to ArcObjects.
You could test what subtype your ESRI.ArcGIS.ADF.Web.Geometry.Geometry adfFeature is and do conversion accordingly.
By the way I suggest that you never use the "as" cast since it can fail silently (just returning null). Instead I suggest:
ESRI.ArcGIS.Geometry.IGeometry featureInterface =
(ESRI.ArcGIS.Geometry.IGeometry)adfFeature;
Then you will see the problem as soon as it occurs.
I am working on a custom ArcGIS Desktop tool project and I would like to implement an automated linear referencing feature in it. To make a long story short, I would like to display problematic segments along a route and show the severity by using a color code (say green, yellow, red, etc.). I know this is a pretty common scenario and have come to understand that the "right way" of accomplishing this task is to create a linear event table which will allow me to assign different codes to certain route segments. Some of my colleagues know how to do it manually but I can't seem to find any way to replicate this programaticaly.
The current tool is written in C# and already performs all the needed calculations to determine the problematic areas. The problem mainly is that I don't know where to start since I don't know a lot about ArcObjects. Any code sample or suggestion is welcome (C# is preferred but C++, VB and others will surely help me anyway).
EDIT :
I'm trying to use the MakeRouteEventLayer tool but can't seem to get the different pre-conditions met. The routes are hosted on an SDE server. So far, I am establishing a connection this way :
ESRI.ArcGIS.esriSystem.IPropertySet pConnectionProperties = new ESRI.ArcGIS.esriSystem.PropertySet();
ESRI.ArcGIS.Geodatabase.IWorkspaceFactory pWorkspaceFactory;
ESRI.ArcGIS.Geodatabase.IWorkspace pWorkspace;
ESRI.ArcGIS.Location.ILocatorManager pLocatorManager;
ESRI.ArcGIS.Location.IDatabaseLocatorWorkspace pDatabaseLocatorWorkspace;
pConnectionProperties.SetProperty("server", "xxxx");
pConnectionProperties.SetProperty("instance", "yyyy");
pConnectionProperties.SetProperty("database", "zzzz");
pConnectionProperties.SetProperty("AUTHENTICATION_MODE", "OSA");
pConnectionProperties.SetProperty("version", "dbo.DEFAULT");
pWorkspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.SdeWorkspaceFactory();
pWorkspace = pWorkspaceFactory.Open(pConnectionProperties, 0);
pLocatorManager = new ESRI.ArcGIS.Location.LocatorManager();
pDatabaseLocatorWorkspace = (ESRI.ArcGIS.Location.IDatabaseLocatorWorkspace)pLocatorManager.GetLocatorWorkspace(pWorkspace);
Now I am stuck trying to prepare everything for MakeRouteEventLayer's constructor. I can't seem to find how i'm supposed to get the Feature Layer to pass as the Input Route Features. Also, I don't understand how to create an event table properly. I can't seem to find any exemple relating to what I am trying to accomplish aside from this one which I don't understand since it isn't documented/commented and the datatypes are not mentionned.
I'm not entirely certain what it is you want to do. If you want to get Linear Referencing values or manipulate them directly in a feature class that already has linear referencing defined, that's pretty straight forward.
IFeatureClass fc = ....;
IFeature feature = fc.GetFeature(...);
IMSegmentation3 seg = (IMSegmentation3)feature;
... blah ...
If you need to create a Feature class with linear referencing, you should start witht he "Geoprocessing" tools in the ArcToolbox. If the out-of-the-box tools can do most of what you need, this will minimize your coding.
I would strongly recommend trying to figure what you need to do with ArcMap if at all possible... then backing out the ArcObjects.
Linear Referencing API
Linear Referencing Toolbox
Understanding Linear Referencing