I've built a method that does create a FeatureLayer (temp_layer). And once that FeatureLayer is created, it is used in a clip operation.
But the clipping part does not work because it cannot recognize the featurelayer (temp_layer).
It's probably linked to the async process.
Anybody has a suggestion about that problem?
Here's the piece a code that does what I've said:
/// <summary>
/// Execute the MakeFeatureLayer Tool in the ArcMap Toolbox.
/// Followed by a clip on that featurelayer.
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
public static async Task<bool> ExecuteMakeFeatureLayerAndClipAsync(string _inputFeatures,
string _outputLayer,
string _clipFClassPath,
string _whereClause = "",
string _workSpace = "",
string _field_Info = "")
{
var environments = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);
List<object> arguments = new()
{
_inputFeatures,
"temp_layer",
_whereClause,
_workSpace,
_field_Info
};
IGPResult result = await Geoprocessing.ExecuteToolAsync("management.MakeFeatureLayer", Geoprocessing.MakeValueArray(arguments.ToArray()), environments, null, null, GPExecuteToolFlags.None);
if (result.IsFailed)
{
Geoprocessing.ShowMessageBox(result.Messages, "GP Messages", GPMessageBoxStyle.Error);
}
arguments = new()
{
"temp_layer",
_clipFClassPath,
_outputLayer,
""
};
result = await Geoprocessing.ExecuteToolAsync("analysis.Clip", Geoprocessing.MakeValueArray(arguments.ToArray()), environments, null, null, GPExecuteToolFlags.None);
if (result.IsFailed)
{
Geoprocessing.ShowMessageBox(result.Messages, "GP Messages", GPMessageBoxStyle.Error);
}
return !result.IsFailed;
}
What I've done when using the result of one GeoProcessing tool in another tool is to get the FeatureClass of the result as an input to the second tool. This is using a geodatabase where everything will be stored. Here's an example:
IGPResult result = await Geoprocessing.ExecuteToolAsync("management.MakeFeatureLayer", Geoprocessing.MakeValueArray(arguments.ToArray()), environments, null, null, GPExecuteToolFlags.None);
if (result.IsFailed)
{
Geoprocessing.ShowMessageBox(result.Messages, "GP Messages", GPMessageBoxStyle.Error);
return; //Exit if the first step fails
}
using (FeatureClass tempFC = geodatabase.OpenDataset<FeatureClass>("temp_layer"))
{
arguments = new()
{
tempFC,
_clipFClassPath,
_outputLayer,
""
};
result = await Geoprocessing.ExecuteToolAsync("analysis.Clip", Geoprocessing.MakeValueArray(arguments.ToArray()), environments, null, null, GPExecuteToolFlags.None);
if (result.IsFailed)
{
Geoprocessing.ShowMessageBox(result.Messages, "GP Messages", GPMessageBoxStyle.Error);
}
return !result.IsFailed;
}
Interesting approach.
But it does not work because I'm using a FeatureLayer which resides in memory only. It is not part of the FGDB. I'm using a feature layer because it should be faster than creating a feature class which will be staying on the FGDB.
The line
using (FeatureClass tempFC = geodatabase.OpenDataset<FeatureClass>("temp_layer"))
returns an error saying the table cannot be found.
I used to do that operation with ArcObjects without any problems, but it does not seem to be the case under ArcGIS PRo SDK.
I have used a memory geodatabase to temporarily copy a feature class and work with it.
MemoryConnectionProperties memoryConnectionProperties = new MemoryConnectionProperties();
using (Geodatabase geodatabase = SchemaBuilder.CreateGeodatabase(memoryConnectionProperties))
{
string path = geodatabase.GetPath().AbsolutePath;
var copyResult = await Utilities.CopyFeatureClass(SelectedFCFeatureLayer.GetFeatureClass(), path, "VirtualInputLayer"); //this is a function to call the "conversion.FeatureClassToFeatureClass" tool
I tried your suggestion, but it did not work because of the line:
string path = geodatabase.GetPath().AbsolutePath;
The GetPath() method return null when the geodatabase is in memory.
So instead, I tried to do a selection followed by a CopyFeatures into memory (using @"memory\") and then the clip, just like this:
public static async Task<bool> ExecuteMakeFeatureLayerAndClipAsync(string _inputFeatures,
string _outputLayer,
string _clipFClassPath,
string _whereClause = "",
string _workSpace = "",
string _field_Info = "")
{
var environments = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);
await ExecuteSelectLayerByAttributeAsync(_inputFeatures, "NEW_SELECTION", _whereClause);
string path = @"memory\";
await ExecuteCopyFeaturesAsync(_inputFeatures, path + "temp_layer");
List<object> arguments = new()
{
path + "temp_layer",
_clipFClassPath,
_outputLayer,
""
};
IGPResult result = await Geoprocessing.ExecuteToolAsync("analysis.Clip", Geoprocessing.MakeValueArray(arguments.ToArray()), environments, null, null, GPExecuteToolFlags.None);
if (result.IsFailed)
{
Geoprocessing.ShowMessageBox(result.Messages, "GP Messages", GPMessageBoxStyle.Error);
}
return !result.IsFailed;
}
It worked, but the performance is not there when I compare it with the code in the old ArcObjects that uses a MakeFeatureLayer followed by a clip.
For the exact same layer containing a lot of records, it used to take 10 seconds using ArcObjects, and under ArcGIS Pro SDK it takes almost 5 minutes.
The problem right now is not being able to use the FeatureLayer created when using "management.MakeFeatureLayer"
That path variable was a result of testing I was doing with different geodatabases. My code was copying an existing FeatureClass into memory, then adding fields to it for some additional analysis. That was working fine in ArcObjects, but not in the Pro SDK. I can't seem to add the fields to a FC in a memory geodatabase, so I have to copy it the geodatabase where the original FC resides, which is much slower.
Well, thanks a lot for the solution you tried to provide. I'll keep digging, and if I find something, I'll do a reply.