private IFeature CreateEmptyGeometryFeature(IFeatureWorkspace ws, esriGeometryType geometryType, IGeometry andAlso = null) { ISpatialReference sr = SpatialReferenceUtils.CreateSpatialReference ((int)esriSRProjCS2Type.esriSRProjCS_CH1903Plus_LV95, true); IFeatureClass featureClass = EnsureFeatureClass(ws, geometryType, geometryType.ToString(), sr); IGdbTransaction transaction = new GdbTransaction(); IFeature feature = null; bool inserted = transaction.Execute((IWorkspace)ws, () => { if (andAlso != null) { andAlso.SpatialReference = sr; IFeature nonEmpty = featureClass.CreateFeature(); nonEmpty.Shape = andAlso; nonEmpty.Store(); } feature = featureClass.CreateFeature(); // NOTE: There is no difference when setting an empty geometry feature.Store(); }, "Insert feature"); Assert.IsTrue(inserted); return(feature); }
/// <summary> /// Fields the SQL geometry. /// </summary> /// <param name="geomtype">The geomtype.</param> /// <param name="geometryFieldName">Name of the geometry field.</param> /// <returns>Spatialite SQL for geometry field (used in Create table SQL statement) </returns> private static string FieldSQLGeometry(esriGeometryType geomtype, string geometryFieldName) { switch (geomtype) { case esriGeometryType.esriGeometryPoint: return(geometryFieldName + " POINT "); case esriGeometryType.esriGeometryPolygon: return(geometryFieldName + " POLYGON "); case esriGeometryType.esriGeometryPolyline: return(geometryFieldName + " LINESTRING "); case esriGeometryType.esriGeometryLine: return(geometryFieldName + " LINESTRING "); case esriGeometryType.esriGeometryAny: case esriGeometryType.esriGeometryBag: case esriGeometryType.esriGeometryBezier3Curve: case esriGeometryType.esriGeometryCircularArc: case esriGeometryType.esriGeometryEllipticArc: case esriGeometryType.esriGeometryEnvelope: case esriGeometryType.esriGeometryMultiPatch: case esriGeometryType.esriGeometryMultipoint: case esriGeometryType.esriGeometryNull: case esriGeometryType.esriGeometryPath: case esriGeometryType.esriGeometryRay: case esriGeometryType.esriGeometryRing: case esriGeometryType.esriGeometrySphere: case esriGeometryType.esriGeometryTriangleFan: case esriGeometryType.esriGeometryTriangleStrip: case esriGeometryType.esriGeometryTriangles: default: Console.WriteLine(geometryFieldName + " skipped. " + geomtype.ToString() + " not supported."); return(null); } }
/// <summary> /// 获取几何类型<see cref="esriGeometryType"/>的中文描述 /// </summary> /// <param name="type"></param> /// <returns></returns> public static string GetGeometryTypeCnName(this esriGeometryType type) { string typeName; switch (type) { case esriGeometryType.esriGeometryPoint: typeName = "点"; break; case esriGeometryType.esriGeometryPolyline: typeName = "线"; break; case esriGeometryType.esriGeometryPolygon: typeName = "面"; break; case esriGeometryType.esriGeometryMultipoint: typeName = "多点"; break; default: typeName = type.ToString().Replace("esriGeometry", ""); break; } return(typeName); }
/// <summary> /// Gets the spatialite geometry type of the IFeatureClass /// </summary> /// <param name="fc">The IFeatureClass.</param> /// <returns>geometry type string (e.g. POINT|LINESTRING|POLYGON|MULTIPOINT)</returns> internal static string GetGeometryType(ref IFeatureClass fc) { esriGeometryType geomType = fc.ShapeType; switch (geomType) { case esriGeometryType.esriGeometryPoint: return("POINT"); case esriGeometryType.esriGeometryPath: case esriGeometryType.esriGeometryPolyline: case esriGeometryType.esriGeometryLine: return("LINESTRING"); case esriGeometryType.esriGeometryEnvelope: case esriGeometryType.esriGeometryPolygon: return("POLYGON"); case esriGeometryType.esriGeometryMultipoint: return("MULTIPOINT"); case esriGeometryType.esriGeometryAny: case esriGeometryType.esriGeometryBag: case esriGeometryType.esriGeometryBezier3Curve: case esriGeometryType.esriGeometryCircularArc: case esriGeometryType.esriGeometryEllipticArc: case esriGeometryType.esriGeometryMultiPatch: case esriGeometryType.esriGeometryNull: case esriGeometryType.esriGeometryRay: case esriGeometryType.esriGeometryRing: case esriGeometryType.esriGeometrySphere: case esriGeometryType.esriGeometryTriangleFan: case esriGeometryType.esriGeometryTriangleStrip: case esriGeometryType.esriGeometryTriangles: default: throw new ArgumentException(geomType.ToString() + " not supported with sde2spatialite.exe"); } }
/// <summary> /// 获取几何类型字符(eg:"Line","Point","Polygon","Polyline","Null"等等) /// </summary> /// <param name="geoType"></param> /// <returns></returns> public static string GetGeoTypeStr(esriGeometryType geoType) { return(geoType.ToString().Replace("esriGeometry", "")); }
/// <summary> /// Creates and Serves vector tiles /// </summary> /// <param name="boundVariables"></param> /// <param name="operationInput"></param> /// <param name="outputFormat"></param> /// <param name="requestProperties"></param> /// <param name="responseProperties"></param> /// <returns></returns> private byte[] VectorTileHandler(NameValueCollection boundVariables, JsonObject operationInput, string outputFormat, string requestProperties, out string responseProperties) { //responseProperties = null; responseProperties = null; //"Content-Type:application/json"; ESRI.ArcGIS.SOESupport.AutoTimer timer = new AutoTimer(); const string methodName = "VectorTileHandler"; try { long? layerIndex; long? zoom; long? row; long? col; string jsonFormatParam; TileFormat jsonFormat = TileFormat.EsriJson; // Defaulting to EsriJson if (!operationInput.TryGetAsLong("l", out layerIndex)) { throw new ArgumentNullException("layer"); } if (!operationInput.TryGetAsLong("z", out zoom)) { throw new ArgumentNullException("zoom"); } if (!operationInput.TryGetAsLong("y", out row)) { throw new ArgumentNullException("row"); } if (!operationInput.TryGetAsLong("x", out col)) { throw new ArgumentNullException("col"); } if (operationInput.TryGetString("jf", out jsonFormatParam)) { if (!string.IsNullOrEmpty(jsonFormatParam)) { jsonFormatParam = jsonFormatParam.ToLower().Trim(); Enum.GetNames(typeof(TileFormat)).ToList().ForEach(n => { if (n.ToLower() == jsonFormatParam) { jsonFormat = (TileFormat)Enum.Parse(typeof(TileFormat), jsonFormatParam, true); } }); } } //System.Diagnostics.Debug.WriteLine(string.Format("l:{0}, r:{1}, c:{2}", zoom, row, col)); // Check to see if the tile exists on disk... // <cache-root>\<layerId>\<zoom>\<row>\<col>.esrijson; //i.e. to be consistent with Esri tile caching structure string tilePath = string.Format(@"{0}\{1}\{2}\{3}\{4}.{5}", _vectorCacheRootDirectory, layerIndex, zoom.Value, row.Value, col.Value, jsonFormat.ToString().ToLower()); if (File.Exists(tilePath)) { // Fetch tile contents from disk _dtsLogger.LogInfo(soe_name, methodName, "Time: " + timer.Elapsed.ToString()); logger.LogMessage(ServerLogger.msgType.infoSimple, methodName, -1, "Time: " + timer.Elapsed.ToString()); return(this.ReadTileFile(tilePath)); } else { // Write new files to disk IMapServer3 mapServer = serverObjectHelper.ServerObject as IMapServer3; if (mapServer == null) { throw new InvalidOperationException("Unable to access the map server."); } // Get the bbox. Returns an envelope in WGS84 (4326). IEnvelope env102100 = TileUtil.GetEnvelopeFromZoomRowCol((int)zoom.Value, (int)row.Value, (int)col.Value); //_dtsLogger.LogInfo(soe_name, methodName, this.GeometryToXml(env4326)); // Convert envelope to polygon b/c QueryData does not support spatialfilter geometry using envelope IPolygon polygon102100 = this.CreatePolygonFromEnvelope(env102100); // Use QueryData and generalize result geometries based on zoom level IQueryResultOptions resultOptions = new QueryResultOptionsClass(); // i.e; IRecordSet to support BOTH json and geojson resultOptions.Format = esriQueryResultFormat.esriQueryResultRecordSetAsObject; IMapTableDescription tableDescription = this.GetTableDescription(mapServer, (int)layerIndex, (int)zoom); // Create spatial filter ISpatialFilter spatialFilter = new SpatialFilterClass(); spatialFilter.Geometry = polygon102100; spatialFilter.GeometryField = "Shape"; spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; //TODO: Subfields should be configurable spatialFilter.SubFields = "*"; // Execute query IQueryResult result = mapServer.QueryData(mapServer.DefaultMapName, tableDescription, spatialFilter, resultOptions); byte[] json = null; // TODO: Support writing tiles for no data // Need a way to do this for GeoJson; parse Esri JSON recordset into GeoJson if (result == null || !this.RecordsetHasFeatures(result.Object as IRecordSet)) { // Write "no data" tile if (jsonFormat == TileFormat.EsriJson) { resultOptions.Format = esriQueryResultFormat.esriQueryResultJsonAsMime; result = mapServer.QueryData(mapServer.DefaultMapName, tableDescription, spatialFilter, resultOptions); json = result.MimeData; } else { json = StrToByteArray(NO_DATA_GEOJSON); } } else { //We have features... IRecordSet features = result.Object as IRecordSet; // Get geometry type for query layer esriGeometryType geometryType = this.GetLayerGeometryType(mapServer.GetServerInfo(mapServer.DefaultMapName).MapLayerInfos, (int)layerIndex); switch (geometryType) { case esriGeometryType.esriGeometryPoint: // Do nothing... already intersected json = ESRI.ArcGIS.SOESupport.Conversion.ToJson(features); break; case esriGeometryType.esriGeometryPolyline: // Polylines must be clipped to envelope IFeatureCursor cursor = null; this.ClipFeaturesToTile(ref cursor, ref features, env102100); json = ESRI.ArcGIS.SOESupport.Conversion.ToJson(features); this.ReleaseComObject(cursor); break; case esriGeometryType.esriGeometryMultipoint: case esriGeometryType.esriGeometryPolygon: // Get IDs of features whose centroid is contained by tile envelope List <int> ids = this.GetIdsOfContainedFeatureCentroids(features, polygon102100); if (ids.Count == 0) { // Write no data tile if (jsonFormat == TileFormat.EsriJson) { // Query to get empty featureset and serialize to disk resultOptions.Format = esriQueryResultFormat.esriQueryResultJsonAsMime; IQueryFilter queryFilter = new QueryFilterClass(); queryFilter.SubFields = "*"; queryFilter.WhereClause = "1=2"; result = mapServer.QueryData(mapServer.DefaultMapName, tableDescription, queryFilter, resultOptions); json = result.MimeData; } else { json = StrToByteArray(NO_DATA_GEOJSON); } } else { // Execute new query for IDs IQueryFilter queryFilter = new QueryFilterClass(); queryFilter.SubFields = "*"; // TODO: Account for sql query syntax based on datasource // FGDB/Shapefile then "OBJECTID"; quotes required // PGDB then [OBJECTID]; brackets required // SDE then OBJECTID; nothing but the fieldname queryFilter.WhereClause = string.Format("\"OBJECTID\" IN({0})", ids.ToDelimitedString <int>(",")); // FGDB result = mapServer.QueryData(mapServer.DefaultMapName, tableDescription, queryFilter, resultOptions); features = result.Object as IRecordSet; // Do some checking here... var featureCount = this.GetRecordsetFeatureCount(features); if (featureCount != ids.Count) { System.Diagnostics.Debug.WriteLine(string.Format("Query Problem: ID search results IS NOT EQUAL to contained IDs count - [{0}:{1}]", featureCount, ids.Count)); System.Diagnostics.Debug.WriteLine("Query: " + queryFilter.WhereClause); } json = ESRI.ArcGIS.SOESupport.Conversion.ToJson(features); } break; default: throw new NotSupportedException(string.Format("Geometry type {0} is not supported by {1}", geometryType.ToString(), soe_name)); } } //store the json to disk this.WriteTileFile(json, tilePath, (int)layerIndex, (int)zoom, (int)row); _dtsLogger.LogInfo(soe_name, methodName, "Time: " + timer.Elapsed.ToString()); logger.LogMessage(ServerLogger.msgType.infoSimple, methodName, -1, "Time: " + timer.Elapsed.ToString()); return(json); } } catch (Exception ex) { // Log the error _dtsLogger.LogError(soe_name, methodName, "n/a", ex); logger.LogMessage(ServerLogger.msgType.error, methodName, 9999, ex.StackTrace); return(StrToByteArray("{}")); } }