POST
|
@CharlesMacleod Thanks! I'm going to be moving my AddIns to 3.0 soon but hadn't looked at what that would entail yet and you're URL gave me a heads up on some things that have changed that I'll need to factor into that work. Specifically that the Add-In Content approach has gone away...
... View more
08-22-2022
03:02 PM
|
0
|
0
|
1365
|
POST
|
@LewisTrotter I'm using GDAL 3.4.1 in conjunction with an Add-In I've developed but I'm not using it directly from C#. I've statically linked it to another C++ library that I am calling from C#. I do this via a SWIG generated interface. Nonetheless the PINVOKE exception is the key to your problem. PINVOKE is a method by which C# code can call C++ code. But that C++ code has to be in a DLL. Last time I checked ArcGIS Pro SDK does not see native dependencies (i.e. on C++ DLLs) and will not copy your DLL to the appropriate C:\Users\<user-name>\AppData\Local\ESRI\ArcGISPro\AssemblyCache folder at run time so your code is trying to load a DLL that is not there. In my case, we decided to use our AddIn Module code to copy all Native DLLs to that directory when the plugin loads. This is because an assembly will search a specific series of directories for a DLL (https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order) and the current directory of the calling process is one of them. A simple check, that requires no code changes, is to put the GDAL 3.5.0 DLL into one of the directory's in your PATH and try again. Good luck!
... View more
08-22-2022
06:30 AM
|
1
|
1
|
1403
|
POST
|
ArcGIS Pro is multi-threaded and its most likely that processes you kicked off have not completed and include geodatabase "refresh" calls that are causing this (not something you did but something GP Tool is doing). Fortunately those processes are not running on the GUI thread which allows you to navigate while these processes are running. But also because of that you can see what you're seeing. I have the same thing happen when I'm processing thousands of features. I general don't navigate to the GDB in the catalog while that's happening unless I want to see if its done (i.e. when it stops flashing). Just my $0.02. But as a feature request it would be nice if they just placed an animated GIF next to the GDB and didn't "flash" it like they do. Would be less annoying and let the user/analyst know what's happening.
... View more
04-19-2022
02:55 PM
|
0
|
0
|
318
|
POST
|
Yes. Completely agree. XAML is definitely not as intuitive as WinForms but works well once you figure it out... 🙂 Unfortunately, I've not placed any checkboxes or combo boxes on the Ribbon as of yet. I've mostly used the Ribbon a button to launch dockpane's and dialogs or a MapTool. On Dockpane's and Dialog's you get a code behind (i.e. *.xaml.cs that is paired with the *.xaml page). I can almost picture what you're trying to do and see that it would be done using the Config.daml for your Add-In but if you could post a picture of the UI you're trying to implement that would help. Also I think it is a bit easier if it's on a Dockpane or in a custom dialog but just my $0.02. Where is the checkbox? Is it on another button on the ribbon or somewhere else? Look forward to seeing what you got. In that environment (i.e. dockpane or dialog) you assign a name to the CheckBox and you can reference it in your code-behind by that name as shown below: // Checkbox in XAML with Name (Sample.xaml)
// ...
<CheckBox x:Name="cbMyCheckBox" IsChecked="false" />
//...
// The checkbox in XAML above can be referenced in Sample.xaml.cs
// As shown below and the IsChecked is a read/write boolean property
void SomeMethod()
{
cbMyCheckBox.IsChecked = true;
} May not be what you're asking but thought I'd show it anyway...
... View more
03-07-2022
12:48 PM
|
0
|
2
|
2150
|
POST
|
I haven't found a good GP Tool solution... So since my coordinates are actually computed in a C++ component I've decided to actually create a Shapefile using GDAL on the C++ side and then pull that into the Geodatabase with a GP Tool. My experience has been that GDAL is extremely fast so I think I'll be happy with the results. But will post update here.
... View more
02-17-2022
07:29 AM
|
0
|
0
|
238
|
POST
|
Thanks... Haven't needed to deal with Shapefiles in a while. But I recall several years ago using GDAL in C++ code and recall it being at least an order of magnitude (if not more) faster in creating shapefiles. Is your shapefile requirement for a legacy system that uses Shapefiles? I only ask because we were entirely shapefile-centric until we made a conscious effort to get everything into feature classes within Geodatabases.
... View more
02-16-2022
11:12 AM
|
1
|
1
|
946
|
POST
|
Wow... How time flies.... Was revisiting this an issue on Bulk Loading after working a lot of other things in the interim. Ultimately I found significant improvement in performance when not calling Execute as often as Create... I'm not sure of the right ratio but I believe back in 2020 it was a 1:1 ratio of calls to EditOperation.Create to EditOperation.Execute. Now I probably have 100's if not 1000's of calls to EditOperation.Create before calling EditOperation.Execute. This makes a significant improvement in performance. Is there a recommend ratio or limit? But onto my specific question..... With even larger datasets since then I've leveraged the Append, Table to Table, and Feature Class to Feature Class GP Tools to bulk copy data into tables and feature classes. They are far more efficient than EditOperation on large datasets. To bulk load data I've used Table to Table to load over a 100K records in seconds from a CSV file. I've also done equally large datasets of point, line, and polygon feature class using Feature Class to Feature Class and Append. But for Table to Table I've only done that with data (i.e. no features). Now I'm looking back at the same code that is referenced in the original 2020 post (reference above). My Add-In calls native C++ code for all the algorithm processing and currently returns the Geometry and attributes in seconds in a data structure that I then traverse using EditOperation to add to the Feature Class that I also create. That process takes 10's of minutes for the Add-In to actually create all the feature classes and features. The geometry and attributes in the CSV are a set of points and attributes for those points that are used to make a large number of 2 point polyline features to be used as inputs to the 3D Line Intersect with Surface GP Tool. I haven't found a simple way to do this in one step so my current plan is to: 1. Write CSV and attributes to CSV file and adding a column to indicate the ID the line the point should be a part of. 2. Once file is written, bulk import points into a Table or Point Feature Class 2. Use Point to Line GP Tool to create the line features from the Point Features Is there an easier and/or more efficient way to do this? We're talking 100's of Thousands upwards of a few million features. Thanks!
... View more
02-16-2022
08:36 AM
|
0
|
1
|
281
|
POST
|
Just out of curiosity which GP Tool are you using now to do this conversion?
... View more
02-16-2022
07:46 AM
|
0
|
3
|
968
|
POST
|
Wow... How time flies.... Was revisiting this issue after working a lot of other things in the interim. Ultimately I found significant improvement in performance when not calling SaveEditsAsync as often as Create... I'm not sure of the right ratio but I believe back then it was a 1:1 ratio of calls to EditOperation.Create to EditOperation.Execute. Now I probably have 100's if not 1000's of calls to EditOperation.Create before calling EditOperation.Execute. Is there a recommended ratio or limit? But that's not why I'm posting again... With even larger datasets then I've used the Append GP Tool and Table to Table to bulk copy load. Which is far more efficient than EditOperation. To bulk load data I've used Table to Table for upwards of 100K records in seconds from a CSV file. I've also done equally large datasets of point, line, and polygon feature class using Feature Class to Feature Class and Append. But for Table to Table I've only done that with data (i.e. no features). Now I'm looking at the original problem that I posted here and the approach I'm trying is to write to a CSV first. My Add-In calls a native C++ code for all the algorithm processing and currently returns the Geometry and attributes in seconds and then it takes 10's of minutes for the AddIn to actually create all the feature classes and features. The geometry and attributes are a set of points and attributes for those points that are used to make a large number of polyline features to be used as inputs to the 3D Line Intersect with Surface GP Tool. Haven't found a simple way to do this in one step so my plan is to: 1. Write CSV and attributes to CSV file 2. Once file is written, bulk import points into a Table or Point Feature Class 2. Use Point to Line GP Tool to create the line features from the Point Features Is there an easier more efficient way to do this? Thanks!
... View more
02-16-2022
07:29 AM
|
0
|
0
|
455
|
POST
|
I'm using ArcGIS Pro version 2.7.2 and the 2.7 SDK. I've created multi-patch features programmatically and I thought it would be simple to create one from a simple shape. Specifically a Sphere. I've looked high and low and haven't found an example or figured out how to do this yet. Via the Pro UI, I can add a Multipatch Feature Class and the Create options allows the interactive creation of a sphere but the MultiPatchBuilder.MakePatch is limited to esriPatchTypes... An help or examples would be greatly appreciated. Thank you!
... View more
05-03-2021
07:21 AM
|
0
|
2
|
1155
|
POST
|
Our team, like you, initially had a method called CreateFeatureLayer but your method like ours was actually calling a GP Tool (CreateFeatureclass_management) that is creating a FeatureClass. And it just so happens that the default behavior of the Geoprocessing.ExecuteToolAsync() method is to also add the FeatureClass to the active map as a FeatureLayer. But there are times you don't want to do this and the accepted solution is the way to go. I would recommend you change the name of your method to CreateFeatureClass. That's what we did and we also added a boolean option to Add to Map that defaults to false so you have the option to do so or not. Additionally, there are times you do need to find if a layer has been added or not and obtain a reference to the same. I prefer the code snippet below unless there is a better one. FeatureLayer l_returnLayer = MapView.Active.Map.FindLayers(a_layerName).FirstOrDefault() as FeatureLayer;
... View more
04-23-2021
03:24 PM
|
0
|
0
|
1439
|
POST
|
I haven't tried the ExcelToTable but I have run a number of GP Tools using the Geoprocessing.ExecuteToolAsync() and I'm thinking most of them are actually in python. Here is a method for running the RasterTIN_3d GP Tool public static async Task<IGPResult> CallRasterToTIN_GPTool(string l_newRaster)
{
string l_outputTIN = Project.Current.HomeFolderPath + @"\Terrain Data\TINs";
// Make the sure the TINs subdirectory exists beneath Terrain Data
if (System.IO.Directory.Exists(l_outputTIN) == false)
{
System.IO.Directory.CreateDirectory(l_outputTIN);
}
l_outputTIN += @"\Range_TIN";
List<object> arguments = new List<object>
{
l_newRaster, // Input Raster
l_outputTIN, // Output TIN
};
var l_returnValue = await Geoprocessing.ExecuteToolAsync("RasterTIN_3d", Geoprocessing.MakeValueArray(arguments.ToArray()), null, null, null, GPExecuteToolFlags.None);
And here is another one for Creating a FeatureClass and optionally adding it to the map using the CreateFeatureclass_managment GP Tool. public static async Task<IGPResult> CreateFeatureClass(string featureclassName, string featureclassType, SpatialReference a_spatialReference, bool a_addToMap = true)
{
System.Diagnostics.Debug.WriteLine(CoreModule.CurrentProject.DefaultGeodatabasePath);
List<object> arguments = new List<object>
{
CoreModule.CurrentProject.DefaultGeodatabasePath, // use the default geodatabase
featureclassName, // name of the feature class
featureclassType, // type of geometry
"", // no template
"DISABLED", // no m values
"ENABLED", // no z values
a_spatialReference
};
if (a_addToMap)
{
IGPResult l_returnResult = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management", Geoprocessing.MakeValueArray(arguments.ToArray()));
if (l_returnResult.IsFailed == false)
{
// Confirm FeatureClass added to map as Layer. The only reason it would not is if user has turned
// on the feature that tells ArcGIS Pro not to add Geoprocessing results to the map
// This logic handles that condition
var l_layerReturned = MapView.Active.Map.FindLayers(featureclassName).FirstOrDefault() as FeatureLayer;
if (l_layerReturned == null)
{
Uri l_layerURI = new Uri(l_returnResult.ReturnValue);
await QueuedTask.Run(()=> LayerFactory.Instance.CreateLayer(l_layerURI, MapView.Active.Map) );
}
}
return l_returnResult;
}
else
{
return await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management", Geoprocessing.MakeValueArray(arguments.ToArray()),null,null,null,GPExecuteToolFlags.None);
}
} You'll notice a pattern of passing a List<object> for each GP Tool. That's the trick is knowing what should be in that list. What I've generally done is make sure I can run the GP Tool via the ArcGIS Pro UI first. When successful, I then click the "Details" Link at the bottom of the Geoprocessing Dockpane and review the Parameters list. I then make sure when I implement it in code that the objects in my list align with Parameters list in the Details dialog as shown in attached screenshot. Good luck! Geoprocessing Tool Details Dialog with Parameters
... View more
04-19-2021
03:24 PM
|
1
|
0
|
833
|
POST
|
Your Button will have an id in the <button> tag found in the Config.daml. If you want to do the equivalent of clicking the button programmatically. You need the following code. Hope that helps. var iCommand = FrameworkApplication.GetPlugInWrapper("<Your Button's ID Goes Here>") as ICommand;
if (iCommand != null && iCommand.CanExecute(null))
iCommand.Execute(null);
... View more
03-17-2021
08:40 AM
|
1
|
0
|
1257
|
POST
|
@ChristopherKoenig and @KimberlySaballett I updated to 2.7 and any of the following Tables strings work in QueryDef for the example now. Thank you and thanks to the development team for fixing this. QueryDef queryDef = new QueryDef
{
// Option 1: Tables = "People INNER JOIN States ON People.FK_STATE_ID = States.OBJECTID LEFT JOIN Homes ON People.OBJECTID = Homes.FK_PEOPLE_ID",
// Option 2: Tables = "(People INNER JOIN States ON People.FK_STATE_ID = States.OBJECTID) LEFT JOIN Homes ON People.OBJECTID = Homes.FK_PEOPLE_ID",
// Option 3:
Tables = "((People INNER JOIN States ON People.FK_STATE_ID = States.OBJECTID) LEFT JOIN Homes ON People.OBJECTID = Homes.FK_PEOPLE_ID)",
SubFields = "People.OBJECTID,People.First_Name, People.Last_Name, People.City, States.Abbreviation, Homes.Address",
};
... View more
01-04-2021
05:27 AM
|
0
|
0
|
1263
|
POST
|
Hmmm.... Not sure why I'm getting this error then.... I'm in the middle of another part of the code right now but took a quick look and didn't see any syntax issues. I ended up doing multiple queries as workaround but if I can get this to work it would clean up the code. Thanks... At least now I know it should be possible. I'll try replicate the problem as you did independent of my Add-In to see what's unique about my add-in.
... View more
11-30-2020
11:48 AM
|
0
|
1
|
1333
|
Title | Kudos | Posted |
---|---|---|
1 | 08-22-2022 06:30 AM | |
1 | 02-16-2022 11:12 AM | |
1 | 04-19-2021 03:24 PM | |
1 | 03-17-2021 08:40 AM | |
1 | 11-20-2020 05:27 AM |
Online Status |
Offline
|
Date Last Visited |
08-23-2022
09:13 AM
|