Beispiel #1
0
        static void CreateGrid(TileInfo tiles, int level, IFeatureWorkspace destination, String name)
        {
            ISpatialReferenceFactory2 sEnv = new SpatialReferenceEnvironment() as ISpatialReferenceFactory2;
            ISpatialReference sr = sEnv.CreateSpatialReference((int)tiles.spatialReference);
            sr.SetMDomain(-137434824702, 0);
            IFeatureClass fc = CreateFeatureClass(destination, name, sr);
            LOD lod = tiles.lods[level];
            double width = tiles.width * lod.resolution;
            double height = tiles.height * lod.resolution;
            double y = tiles.originY;
            long row = 0;
            double maxX = -(tiles.originX + width);
            double minY = -(tiles.originY - height);
            while (y > minY)
            {
                double x = tiles.originX;
                long col = 0;
                while (x < maxX)
                {
                    RingClass ring = new RingClass();
                    IPoint tl = new PointClass();
                    tl.PutCoords(x, y);
                    tl.M = -(((col & 0xFFFF) << 16) + (row & 0xFFFF));
                    ring.AddPoint(tl);
                    IPoint tr = new PointClass();
                    tr.PutCoords(x + width, y);
                    tr.M = -((((col + 1) & 0xFFFF) << 16) + (row & 0xFFFF));
                    ring.AddPoint(tr);
                    IPoint br = new PointClass();
                    br.PutCoords(x + width, y - width);
                    br.M = -((((col + 1) & 0xFFFF) << 16) + ((row + 1) & 0xFFFF));
                    ring.AddPoint(br);
                    IPoint bl = new PointClass();
                    bl.PutCoords(x, y - width);
                    bl.M = -(((col & 0xFFFF) << 16) + ((row + 1) & 0xFFFF));
                    ring.AddPoint(bl);

                    ring.AddPoint(tl);

                    ring.Close();
                    PolygonClass polygon = new PolygonClass();
                    polygon.AddGeometry(ring);
                    IFeature polyFeature = fc.CreateFeature();
                    polyFeature.Shape = polygon;
                    polyFeature.Store();
                    x += width;
                    col += 1;
                }
                row += 1;
                y -= height;
            }
            IFeatureClassDescriptor fd = new FeatureClassDescriptorClass();
            fd.Create(fc, null, "OBJECTID");
        }
 private byte[] ExtractByPolygonHandler(NameValueCollection boundVariables,
     JsonObject operationInput,
     string outputFormat,
     string requestProperties,
     out string responseProperties)
 {
     string search_id;
     bool found = operationInput.TryGetString("search_id", out search_id);
     if (!found || string.IsNullOrEmpty(search_id))
     {
         throw new ArgumentNullException("search_id");
     }
     // input polygon - REQUIRED - the polygon to summarise data within
     JsonObject jsonPolygon;
     found = operationInput.TryGetJsonObject("polygon", out jsonPolygon);
     if (!found)
     {
         throw new ArgumentNullException("polygon");
     }
     IPolygon extractionPolygon = Conversion.ToGeometry(jsonPolygon, esriGeometryType.esriGeometryPolygon) as IPolygon;
     long? jsonWkid;
     found = operationInput.TryGetAsLong("input_wkid", out jsonWkid);
     if (!found)
     {
         throw new ArgumentNullException("input_wkid", "WKID numeric value for spatial reference of input point must be provided");
     }
     if (jsonWkid.HasValue)
     {
         int wkid = (int)jsonWkid.Value;
         ISpatialReferenceFactory2 tInSRFac = new SpatialReferenceEnvironment() as ISpatialReferenceFactory2;
         ISpatialReference tInSR = tInSRFac.CreateSpatialReference(wkid);
         extractionPolygon.SpatialReference = tInSR;
     }
     else
     {
         // we won't get here
         extractionPolygon.SpatialReference = new UnknownCoordinateSystemClass();
     }
     bool? reqReturnAsAttributes;
     bool returnAsAttributes = false;
     found = operationInput.TryGetAsBoolean("extractToPolygonAttributes", out reqReturnAsAttributes);
     if (found && reqReturnAsAttributes.HasValue)
     {
         returnAsAttributes = (bool)reqReturnAsAttributes;
     }
     List<ExtractionLayerConfig> extractionRequests = new List<ExtractionLayerConfig>();
     foreach (ExtractionLayerConfig tExtLayerInfo in m_ExtractableParams)
     {
         string jsonParam = tExtLayerInfo.ParamName;
         bool? wasRequested;
         found = operationInput.TryGetAsBoolean(jsonParam, out wasRequested);
         if (found && wasRequested.HasValue && (bool)wasRequested)
         {
             extractionRequests.Add(tExtLayerInfo);
         }
     }
     logger.LogMessage(ServerLogger.msgType.debug, "ExtractByPolygonHandler", 99,
                   "Processed inputs, attempting " + extractionRequests.Count.ToString() + " extractions");
     // now need to convert the IPolygon to a geodataset, (a polygon one) for feature
     // extractions.
     IWorkspace inMemWksp = CreateInMemoryWorkspace() as IWorkspace;
     IFeatureWorkspace inMemFeatWksp = inMemWksp as IFeatureWorkspace;
     IFeatureClass tPolyAsFC = CreateFeatureClassFromGeometry(extractionPolygon, inMemFeatWksp, extractionPolygon.SpatialReference.FactoryCode);
     IArea tArea = extractionPolygon as IArea;
     if (AddAField(tPolyAsFC,"Total_Area",esriFieldType.esriFieldTypeDouble))
     {
         IFeatureCursor tFCursor = tPolyAsFC.Search(null,false);
         IFeature tPolyAsFeature = tFCursor.NextFeature();
         tPolyAsFeature.set_Value(tPolyAsFC.FindField("Total_Area"),tArea.Area);
         tPolyAsFeature.Store();
     }
     IGeoDataset tPolygonGDS = tPolyAsFC as IGeoDataset;
     // now do the extractions from it
     ExtractionResultCollection tExtractionResults =
         ProcessExtractions(search_id,tPolygonGDS, null, extractionRequests);
     // Warning! Don't go assuming that the suggestively-named responseProperties can be set to anything
     // helpful to describe, say, response properties. Try setting it to anything other than null
     // (that I have tried) and you get "500 Unexpected Error" message and lose the best part of an
     // afternoon working out why!
     //responseProperties = "Extractions processed successfully";
     responseProperties = null;
     logger.LogMessage(ServerLogger.msgType.debug, "ExtractByPolygonHandler", 99,
                   "Extractions complete, returning feature");
     if (returnAsAttributes)
     {
         IRecordSetInit returnRecSet = new RecordSetClass();
         IGeoDataset tFinalGDS = tExtractionResults.ResultsAsAttributedGeodataset;
         returnRecSet.SetSourceTable(tFinalGDS as ITable, null);
         IRecordSet recset = returnRecSet as IRecordSet;
         byte[] jsonFeature = Conversion.ToJson(recset);
         return jsonFeature;
     }
     else
     {
         JsonObject tResultsAsJson = tExtractionResults.ResultsAsJson;
         byte[] jsonFeatures = System.Text.Encoding.UTF8.GetBytes(tResultsAsJson.ToJson());
         return jsonFeatures;
     }
 }
        private byte[] CreateWatershedHandler(NameValueCollection boundVariables,
            JsonObject operationInput,
            string outputFormat,
            string requestProperties,
            out string responseProperties)
        {
            responseProperties = null;

            #region Process the REST arguments
            // hydroshed_id - REQUIRED - to identify the overall result
            string search_id;
            bool found = operationInput.TryGetString("search_id", out search_id);
            if (!found || string.IsNullOrEmpty(search_id))
            {
                throw new ArgumentNullException("search_id");
            }
            // input point - REQUIRED - the search location
            JsonObject jsonPoint;
            found = operationInput.TryGetJsonObject("location", out jsonPoint);
            if (!found)
            {
                throw new ArgumentNullException("location");
            }
            IPoint locationpoint = Conversion.ToGeometry(jsonPoint, esriGeometryType.esriGeometryPoint) as IPoint;
            long? jsonWkid;
            found = operationInput.TryGetAsLong("input_wkid", out jsonWkid);
            if (!found)
            {
                throw new ArgumentNullException("input_wkid", "WKID numeric value for spatial reference of input point must be provided");
            }
            if (jsonWkid.HasValue)
            {
                int wkid = (int)jsonWkid.Value;
                ISpatialReferenceFactory2 tInSRFac = new SpatialReferenceEnvironment() as ISpatialReferenceFactory2;
                ISpatialReference tInSR = tInSRFac.CreateSpatialReference(wkid);
                locationpoint.SpatialReference = tInSR;
            }
            // extent - OPTIONAL - we will use full extent if not provided but this is slow!!
            // TODO maybe preferable to have the extent looked up in the SOE rather than expecting it as a parameter
            JsonObject jsonExtent;
            found = operationInput.TryGetJsonObject("extent", out jsonExtent);
            IGeometry tAnalysisEnvelope;
            if (found && jsonExtent != null)
            {
                logger.LogMessage(ServerLogger.msgType.debug, "process input params", 8000, "Found input extent json object ");
                tAnalysisEnvelope = convertAnyJsonGeometry(jsonExtent);
                logger.LogMessage(ServerLogger.msgType.debug, "process input params", 8000, "Input extent processed ok ");
                try
                {
                    logger.LogMessage(ServerLogger.msgType.debug, "process input params", 8000, "Input extent height*width are: " + tAnalysisEnvelope.Envelope.Height.ToString() + " * " + tAnalysisEnvelope.Envelope.Width.ToString());
                }
                catch (NullReferenceException nre)
                {
                    logger.LogMessage(ServerLogger.msgType.debug, "Processing parameters", 8000, "Problem reading input extent, exception was " + nre.Message + " at " + nre.StackTrace);
                }
            }
            else
            {
                tAnalysisEnvelope = null;
                logger.LogMessage(ServerLogger.msgType.debug, "process input params", 8000, "No input extent parameter requested ");
            }
            List<ExtractionLayerConfig> extractionRequests = new List<ExtractionLayerConfig>();
            foreach (ExtractionLayerConfig tExtLayerInfo in m_ExtractableParams)
            {
                string jsonParam = tExtLayerInfo.ParamName;
                bool? wasRequested;
                found = operationInput.TryGetAsBoolean(jsonParam, out wasRequested);
                if (found && wasRequested.HasValue && (bool)wasRequested)
                {
                    extractionRequests.Add(tExtLayerInfo);
                }
            }
            // check whether to return as json structured object or all flattened onto attributes of the
            // polygon
            bool returnAsPolygonAttributes=false;
            if (extractionRequests.Count > 0)
            {
                bool? nullableBool;
                found = operationInput.TryGetAsBoolean("extractToPolygonAttributes", out nullableBool);
                if (found && nullableBool.HasValue)
                {
                    returnAsPolygonAttributes = (bool)nullableBool;
                }
            }
            #endregion

            #region Do the actual watershed extraction
            // Modified the computeWatershed method to return both the raster and converted polygon versions of the
            // watershed. Because the polygon version, if made by unioning separate polygons, is multipart, and
            // although this is what we want to return to the user, the raster extraction operations can't handle
            // that so we run them with a raster mask input instead. Returning both here saves the extraction methods
            // from converting back to a raster.
            IGeoDataset tWatershedPolyGDS;
            IGeoDataset tWatershedRasterGDS;
            if (tAnalysisEnvelope != null)
            {
                KeyValuePair<IGeoDataset, IGeoDataset> tPair = computeWatershed(locationpoint, tAnalysisEnvelope.Envelope);
                tWatershedPolyGDS = tPair.Value;
                tWatershedRasterGDS = tPair.Key;
            }
            else
            {
                try
                {
                    IEnvelope tAnalysisActuallyAnEnvelope = GetAnalysisEnvelope(locationpoint);
                    KeyValuePair<IGeoDataset, IGeoDataset> tPair = computeWatershed(locationpoint, tAnalysisActuallyAnEnvelope);
                    tWatershedPolyGDS = tPair.Value;
                    tWatershedRasterGDS = tPair.Key;
                }
                catch
                {
                    // error getting the extent. Compute watershed without one (will be slow).
                    KeyValuePair<IGeoDataset, IGeoDataset> tPair = computeWatershed(locationpoint, null);
                    tWatershedPolyGDS = tPair.Value;
                    tWatershedRasterGDS = tPair.Key;
                }
            }
            #endregion
            #region Modify the default fields in polygon catchment
            // raster-to-poly conversion adds some fields we don't want - remove them
            // also we will return the search id, and the corresponding outlet coordinates as
            // attributes on the catchment
            try
            {
                IFeatureClass tPolygonAsFC = (IFeatureClass)tWatershedPolyGDS;
                // these get made by raster-poly conversion and they're boring
                TryDeleteAField(tPolygonAsFC, "GRIDCODE");
                TryDeleteAField(tPolygonAsFC, "ID");
                // Now then now then. After an irritating Thursday afternoon i've discovered that we can't use
                // tPolygonAsFC.GetFeature(1). Because 1 doesn't mean the first one in the FC, but the one with
                // OID = 1. If there were multiple polygons that got deleted and replaced by a single unioned one, then
                // the unioned one won't have OID = 1, as OIDs aren't reused. So we have to use a cursor to get the
                // feature instead. Add all the fields first, to save having to redo the feature retrieval from the
                // cursor, then set them if they added ok.
                bool addedSearchId = AddAField(tPolygonAsFC, "search_id", esriFieldType.esriFieldTypeString, search_id.Length);
                bool addedOutletX = AddAField(tPolygonAsFC, "outlet_x", esriFieldType.esriFieldTypeDouble);
                bool addedOutletY = AddAField(tPolygonAsFC, "outlet_y", esriFieldType.esriFieldTypeDouble);
                IFeature tCatchmentFeature;
                IFeatureCursor tFeatureCursor = tPolygonAsFC.Search(null, false);
                tCatchmentFeature = tFeatureCursor.NextFeature(); // there will only be one, not bothering with loop
                if (addedSearchId)
                {
                    try
                    {
                        tCatchmentFeature.set_Value(tCatchmentFeature.Fields.FindField("search_id"), search_id);
                        tCatchmentFeature.Store();
                    }
                    catch (Exception ex)
                    {
                        logger.LogMessage(ServerLogger.msgType.debug, "create watershed handler", 99, "error setting search id field with value " +
                            search_id + ". Detail: " + ex.StackTrace + " " + ex.Message);
                    }
                }
                if (addedOutletX)
                {
                    try
                    {
                        tCatchmentFeature.set_Value(tCatchmentFeature.Fields.FindField("outlet_x"), locationpoint.X);
                        tCatchmentFeature.Store();
                    }
                    catch (Exception ex)
                    {
                        logger.LogMessage(ServerLogger.msgType.debug, "create watershed handler", 99, "error setting outlet x field with value " +
                            locationpoint.X + ". Detail: " + ex.StackTrace + " " + ex.Message);
                    }
                }
                if (addedOutletY)
                {
                    try
                    {
                        tCatchmentFeature.set_Value(tCatchmentFeature.Fields.FindField("outlet_y"), locationpoint.Y);
                        tCatchmentFeature.Store();
                    }
                    catch (Exception ex)
                    {
                        logger.LogMessage(ServerLogger.msgType.debug, "create watershed handler", 99, "error setting outlet y field with value " +
                            locationpoint.Y + ". Detail: " + ex.StackTrace + " " + ex.Message);
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogMessage(ServerLogger.msgType.debug, "create watershed handler", 99, "some weird problem setting fields in output polygon" + ex.Message + ex.TargetSite.Name + ex.StackTrace + ex.InnerException.Message);
            }
            #endregion
            bool tPolygonIsMultipart = false;
            {
                IFeatureClass tPolygonAsFC = (IFeatureClass)tWatershedPolyGDS;
                IFeatureCursor tFeatureCursor = tPolygonAsFC.Search(null, false);
                IFeature tCatchmentFeature = tFeatureCursor.NextFeature();
                IPolygon tCatchmentPolygon = (IPolygon)tCatchmentFeature.ShapeCopy;
                tPolygonIsMultipart = tCatchmentPolygon.ExteriorRingCount > 1;
            }
            logger.LogMessage(ServerLogger.msgType.debug, "create watershed handler", 99, "created watershed polygon, proceeding with extractions");
            #region Do the catchment characteristic extractions, if any
            // Use the catchment feature (both vector and original raster versions) as input into the generic
            // extraction method
            // will return one with nothing in if there are no extraction requests
            ExtractionResultCollection tExtractionResults =
                ProcessExtractions(search_id, tWatershedPolyGDS, tWatershedRasterGDS, extractionRequests);
            //IGeoDataset tFinalPolygonGDS = ProcessExtractions(tWatershedPolyGDS, tWatershedRasterGDS, extractionRequests);
            #endregion
            // The catchment feature now exists and we also have all the attributes requested. Ready to go.
            // Return either as attributes on the feature itself or as a structured JSON object
            if (returnAsPolygonAttributes)
            {
                IRecordSetInit returnRecSet = new RecordSetClass();
                IGeoDataset tFinalPolygonGDS = tExtractionResults.ResultsAsAttributedGeodataset;
                returnRecSet.SetSourceTable(tFinalPolygonGDS as ITable, null);
                IRecordSet recset = returnRecSet as IRecordSet;
                byte[] jsonFeatures = Conversion.ToJson(recset);
                return jsonFeatures;
            }
            else
            {
                JsonObject tResultsAsJson = tExtractionResults.ResultsAsJson;
                byte[] jsonFeatures = System.Text.Encoding.UTF8.GetBytes(tResultsAsJson.ToJson());
                return jsonFeatures;
            }
        }
        private IFeatureClass CreateFeatureClassFromGeometry(IGeometry pGeometry, IFeatureWorkspace pOutFeatWorkspace, int wkid)
        {
            // thanks to http://bcdcspatial.blogspot.co.uk/2011/12/some-random-arcobjects-that-make.html
            // which was the only place i could find an answer to the problem I was having - the last
            // argument to createfeatureclass is null NOT an empty string
            try
            {
                IFields tFields = new FieldsClass() as IFields;
                IFieldsEdit tFieldsEdit = (IFieldsEdit)tFields;
                IField tShpFld = new Field();
                IFieldEdit tShpEd = (IFieldEdit)tShpFld;
                tShpEd.Type_2 = esriFieldType.esriFieldTypeGeometry;
                tShpEd.Name_2 = "Shape";

                IGeometryDef tGeomDef = new GeometryDef();
                IGeometryDefEdit tGdEdit = (IGeometryDefEdit)tGeomDef;
                tGdEdit.GeometryType_2 = pGeometry.GeometryType;

                ISpatialReferenceFactory2 tSRFac = new SpatialReferenceEnvironment() as ISpatialReferenceFactory2;
                ISpatialReference tSpatRef = tSRFac.CreateSpatialReference(wkid);
                ISpatialReferenceResolution tSpatRefRes = (ISpatialReferenceResolution)tSpatRef;
                tSpatRefRes.ConstructFromHorizon();

                tGdEdit.SpatialReference_2 = tSpatRef;
                tShpEd.GeometryDef_2 = tGeomDef;
                tFieldsEdit.AddField(tShpFld);

                IObjectClassDescription tOCDesc = new FeatureClassDescription();
                for (int i = 0; i < tOCDesc.RequiredFields.FieldCount; i++)
                {
                    IField tField = tOCDesc.RequiredFields.get_Field(i);
                    if (tFieldsEdit.FindField(tField.Name) == -1)
                    {
                        tFieldsEdit.AddField(tField);
                    }
                }
                string tFCName = "tmp" + Guid.NewGuid().ToString("N");
                IFeatureClass tFC = pOutFeatWorkspace.CreateFeatureClass(
                    tFCName, tFields, null, null, esriFeatureType.esriFTSimple, "Shape", null);
                IFeature tGeomAsFeature = tFC.CreateFeature();
                tGeomAsFeature.Shape = pGeometry;
                tGeomAsFeature.Store();
                return tFC;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                logger.LogMessage(ServerLogger.msgType.error, "CreateFeatureClassFromGeometry", 99,
                              "Could not create feature class " + e.Message + e.Source + e.StackTrace);
                throw e;

            }
        }