|
POST
|
Thanks Ken, the windows cursor seems to be more stable than the IMouseCursor one. I will give the StatusStrip with a progress bar/message a try. I have never tried that before, do you have some code I could look at? Thanks! Carlos
... View more
04-10-2012
06:57 AM
|
0
|
0
|
1850
|
|
POST
|
Rich, Thanks for your reply. Yes, I have tried using the IProcessDialog and it works fine but I was trying to avoid opening yet another pop-up form. My boss REALLY likes how the progressbar set to marquee looks and wants the fewest pop-ups/forms as possible so I was trying to get it to work that way first and only go with the IProcessDialog as a last resort. I have never tried setting the Windows cursor to a wait one. Can you show me how to do that? Thanks for your help and time, I really appreciate it! Carlos I have found the IMouseCursor to behave strangely so tend to avoid it. I think each time your code calls external methods then you need to call .SetCursor() again. Have you looked into using IProgressDialog? You can use it with a step progressor bar if you know how many iterations the process will take. If you don't know then hide the step progressor as shown below:
//CREATE OBJECT TO ALLOW USER TO CANCEL
ITrackCancel trackCancel = new CancelTrackerClass();
trackCancel.CancelOnClick = true;
trackCancel.CancelOnKeyPress = true;
//CREATE A PROGRESS DIALOG
IProgressDialogFactory progDialogFact = new ProgressDialogFactoryClass();
IStepProgressor stepProg = progDialogFact.Create(trackCancel, Handle.ToInt32());
IProgressDialog2 progDialog = (IProgressDialog2)stepProg;
progDialog.CancelEnabled = true;
progDialog.Description = "Querying database...";
progDialog.Title = "Progress Dialog Title Here";
progDialog.Animation = esriProgressAnimationTypes.esriProgressGlobe;
stepProg.Message = "Click below to Cancel...";
stepProg.Hide(); Don't forget to close the dialog in your Finally block: progDialog.HideDialog(); This progess dialog will not be embeded in your form but pop up in front. However, I have found it to be the most reliable way to show the user that lengthy background processes are occuring. For shorter processes where a WinForm remains open you may just want to set the Windows cursor to a wait one.
... View more
04-10-2012
03:02 AM
|
0
|
0
|
1850
|
|
POST
|
Hi everyone, I've been fighting with this problem for almost a week now and I am no closer to a solution than when I started so I am hoping someone has some ideas for me. I've read LOTS of ESRI documentation as well as lots of forums post asking similar things but no concrete solutions. I have a form where the user enters a number to search for into an input box. When the user clicks the OK button, the search code runs. The problem is that the search code takes several minutes to complete and I want to give the user some indication that the code is running and not locked up. I've tried to set the MouseCursor to hourglass but it's not consistent for some reason, sometimes the hourglass stays on for the entire search like I want it to do and sometimes it does not. So, I have added a progress bar to my menu below in the input box and set it's ProgressBarStyle to Marquee. I can turn the progress bar on (visible = true) and it updates once but after that, the bar does not move anymore and the progress bar goes away (visible = false) when the search is done. WAY back in the AML days, I could display a "please wait" form on top of the search form in a separate thread until the search was over and then get rid of the thread. Trying to do the same here except figured I would get fancier and put the progress bar on the main form instead of opening another form. I've read some ESRI documents that at times seems to indicate this is not doable but I am not sure. Can someone help me out with some sample code or at least give me a yes or no on whether what I am trying to do is even possible or should I abandon my current code and try something else. I am programming in C# using ArcGIS 9.3 and Visual Studio 2008 and .NET 3.5 Thanks, Carlos
... View more
04-09-2012
01:41 PM
|
0
|
6
|
4316
|
|
POST
|
Alexander, Thank you so much for the reply, I really appreciate it! I think I understand the majority of what you are saying. I'm very much a visual learner. Do you happen to have some code examples (or even pseudo code) showing the logic you are talking about? I've never done custom exceptions before. Thanks again for your help and time! Carlos A clean way of doing it is taking all the return values and making them input variables by ref to the function and retuning a boolean that is success or fail. In some coding styles that is pretty standard. Another way of doing is raising your own exception in the catch block. You can use an application exception or create your own custom .net exception, you can put your own message, or pass in the first exception into the new exception. You can even re-throw the same exception you caught. Creating a custom exception allows you to catch it separately (if you define a catch block with a specific type of exception, you will only catch that type of exception.) You can have more than one catch block for different exception types. Personally, I try to only put try catch blocks at the highest possible level in the code, at the event handler level. For example in an OnClick event of an Icommand. Any exception that happens in a call to a procedure will automatically bubble up to the highest level to be caught. So you handler in procedure 1 will catch exceptions raised in procedure 2. Exception handling can be performance intensive and putting it in private functions or worse in non user interface classes is usually not an good idea (exception made when an edit operation needs to be terminated correctly on exception.) The reason for that is imagine if someone re-uses your code and calls it in a loop and it generates and catches/logs/deals with hundreds of exceptions. This also allows you to deal with exceptions differently with the same code base for example, on a form (errorProvider), an ArcGIS command or tool (message box), an edit session (abort operation), an exe (write to console), a service (write to event log or database.) Also, if you know an exception condition is likely to occur, it is not an exception any more, you are better off checking for the condition than using the exception handling.
... View more
01-23-2012
05:00 AM
|
0
|
0
|
572
|
|
POST
|
Hi everyone, This is more of a .NET question than an ArcObjects question so my apologies for posting here but the IT department of my company has the Internet locked down quite tightly where all discussion groups are automatically blocked and unfortunately, most coding sites fall into this category. The only reason I can get to the ESRI forums is because the site belongs to ESRI and we have lots of ArcGIS licenses. I'm hoping someone can provide me with an answer or at least point me in the right direction. I am developing in C# using .NET 4.0 and ArcGIS 9.3 but I'm pretty sure I can convert code samples in almost any language. For the sake of simplicity, say you have two procedures, 1 and 2. Procedure 1 does some processing calls procedure 2 and when control returns to procedure 1, it takes the output from procedure 2 and does some additional processing. My problem occurs when procedure 2 has an issue (crashes) and control returns to procedure 1. I have error handlers in all of my procedures and they are all like this: public static void ApplyDefinitionQuery(IFeatureLayer featureLayer, string definitionQuery)
{
IFeatureLayerDefinition pFeatureLayerDefinition = null;
try
{
pFeatureLayerDefinition = featureLayer as IFeatureLayerDefinition;
pFeatureLayerDefinition.DefinitionExpression = definitionQuery;
}
catch (Exception ex)
{
ClsLogErrors.LogError(ex.StackTrace, ex.Message, "ApplyDefinitionQuery", null);
MessageBox.Show("The RegGSS Extension encountered a problem." + "\r\n" + "The Regulatory GIS Section has been notified.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (pFeatureLayerDefinition != null) { Marshal.ReleaseComObject(pFeatureLayerDefinition); pFeatureLayerDefinition = null; }
}
} If procedure 2 crashes, the error handler catches the error and writes it out to a database for later debugging. This all works fine. Problem is, if procedure 2 crashes, I don't want procedure 1 to continue when control returns to it. How can I get all the code to stop executing if procedure 2 bombs? The only way I can think of doing it is to make Procedure 2 return a boolean depending on if it succeded or not. However, this becomes a problem too because the majority of our procedures already return something, array, string, etc. and as far as I know, you cannot return more than one value from a procedure. Hope this makes sense. Thanks for your time. Carlos
... View more
01-23-2012
03:33 AM
|
0
|
2
|
1036
|
|
POST
|
Samham, Thanks for the reply! pAppLayer is in a file geodatabase and pEnsLayer is in SDE. Not sure I follow you when you say, "From my experience arcobjects should never be instantiated in every iteration of while loop if possible." Do you have an example of what you mean? I will be out until Monday so my appologies ahead of time if I am late replying to any replies you post. Thanks again! Carlos How many records are stored in pAppLayerand pEnsLayer? Is it sde?
... View more
10-26-2011
01:37 PM
|
0
|
0
|
1259
|
|
POST
|
Hi everyone, I am writing a standalone C# application for creating jpg maps that is being converted from VBA. With help from several people on the forums, I have been able to get everything working without having to use ArcMap at all. I am down to just one glitch and can't figure out how to get around it. At one point, I add a scalebar to the layout and depending on the map scale, I set the units of the scale bar to either esriMiles or esriFeet. The problem I am having is that since I am not running ArcMap and this is all being done in memory, I don't really have map scale to adjust. In the code below, I get an error at if (m_pMap.MapScale >= 25000) with an error of "The data necessary to complete this operation is not yet available." I have seen a couple of similar posts on the forums but no firm solutions. I have tried everything suggested on these threads including making sure the map has a spatial reference and units. Later on in another method, I use the map scale also to set the scale to a rounded number (24,000 instead of 24,323) since the layout also has a scale text object. How can I get/set the map scale if I am not using ArcMap? Any help is greatly appreciated!!! Carlos public static void AddScaleBar()
{
try
{
stdole.StdFont pFont = new stdole.StdFont();
pFont.Name = "Arial";
ITextSymbol pTextSymbol = new TextSymbolClass();
pTextSymbol.Font = pFont as stdole.IFontDisp;
pTextSymbol.Size = 5;
IGraphicsContainer pGraphicsContainer = m_pPageLayout as IGraphicsContainer;
IFrameElement pFrameElement = pGraphicsContainer.FindFrame(m_pMap);
IMapFrame mapFrame = pFrameElement as IMapFrame;
IUID uid = new UIDClass();
uid.Value = "esriCarto.AlternatingScaleBar";
IMapSurroundFrame mapSurroundFrame = mapFrame.CreateSurroundFrame(uid as UID, null);
IElement element = mapSurroundFrame as IElement;
IEnvelope envelope = new EnvelopeClass();
envelope.PutCoords(1.24, 0.4, 3.58, 0.55);
element.Geometry = envelope;
pGraphicsContainer.AddElement(element, 0);
IMapSurround mapSurround = mapSurroundFrame.MapSurround;
IScaleBar pScaleBar = mapSurround as IScaleBar;
pScaleBar.Divisions = 1;
pScaleBar.Subdivisions = 2;
pScaleBar.DivisionsBeforeZero = 0;
pScaleBar.LabelSymbol = pTextSymbol;
pScaleBar.UnitLabelPosition = esriScaleBarPos.esriScaleBarBelow;
pScaleBar.UnitLabelSymbol.HorizontalAlignment = esriTextHorizontalAlignment.esriTHACenter;
pScaleBar.UnitLabelSymbol = pTextSymbol;
pScaleBar.UnitLabelSymbol.Font = pFont as stdole.IFontDisp;
pScaleBar.UnitLabelSymbol.Size = pTextSymbol.Size;
pScaleBar.Name = "scalebar";
//if map scale is greater than 25000, switch the scale units to miles
if (m_pMap.MapScale >= 25000)
pScaleBar.Units = esriUnits.esriMiles;
else
pScaleBar.Units = esriUnits.esriFeet;
IGraphicsContainerSelect pGraphicsContainerSelect = pGraphicsContainer as IGraphicsContainerSelect;
pGraphicsContainerSelect.UnselectAllElements();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
... View more
08-23-2011
07:40 AM
|
0
|
3
|
4277
|
|
POST
|
Hi Ken, Thanks for the reply. You are right on, I did not have pGeoprocessor.OverwriteOutput = "true" set. I added that line to the code below and now it gets further along but after a couple hundred records or so, it starts failing every time the method below gets called (inside loop of another method) and the error is "Object reference not set to an instance of an object." I know what's happening, but no clue as to why. The problem occurs because line: ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet as ISelectionSet; suddenly stops returning a selection set. This line should always return something because the method only gets called when a spatial query determines that two polygons from different layers intersect each other so I don't understand why suddenly it stops working. Sounds like a memory leak or object not being cleared correctly but I've tried adding lines like, if (pWorkspaceFactory != null) { Marshal.ReleaseComObject(pWorkspaceFactory); pWorkspaceFactory = null; } for every object to clear it but it doesn't help. I can post the method calling this method if you want. Just have to do it in another message because it's too large to fit in this one. Thanks again for your help and time, I appreciate it!!! public static bool DetermineOverlapArea3(IFeatureLayer pAppLayer, IFeatureLayer pEnsLayer,
IFeature pAppFeature, IFeature pEnsFeature)
{
try
{
IQueryFilter queryFilter = new QueryFilterClass();
IDataset pDataset1 = null;
IDataset pDataset2 = null;
IFeatureSelection pFeatureSelection1 = null;
IFeatureSelection pFeatureSelection2 = null;
IFeatureClassName pInFeatureClassName1 = new FeatureClassNameClass();
IFeatureClassName pInFeatureClassName2 = new FeatureClassNameClass();
IDatasetName pInDatasetName1 = null;
IDatasetName pInDatasetName2 = null;
IFeatureClassName pOutFeatureClassName1 = new FeatureClassNameClass();
IFeatureClassName pOutFeatureClassName2 = new FeatureClassNameClass();
IDatasetName pOutDatasetName1 = null;
IDatasetName pOutDatasetName2 = null;
IWorkspaceFactory pWorkspaceFactory = new InMemoryWorkspaceFactoryClass();
IFeatureLayer pFeatureLayer = new FeatureLayerClass();
IFeatureWorkspace pFeatureWorkspace = null;
IWorkspaceName pWorkspaceName = new WorkspaceNameClass();
pWorkspaceName = pWorkspaceFactory.Create("", "TEMP", null, 0);
IName pName = pWorkspaceName as IName;
IWorkspace pWorkspace = pName.Open() as IWorkspace;
pFeatureWorkspace = pWorkspace as IFeatureWorkspace;
if (pAppLayer != null)
{
pFeatureSelection1 = pAppLayer as IFeatureSelection;
queryFilter.WhereClause = "APP_NO = '" + m_AppNo + "'";
pDataset1 = pAppLayer.FeatureClass as IDataset;
pFeatureSelection1.SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
pInFeatureClassName1 = pDataset1.FullName as IFeatureClassName;
pInDatasetName1 = pInFeatureClassName1 as IDatasetName;
pOutDatasetName1 = pOutFeatureClassName1 as IDatasetName;
pOutDatasetName1.Name = "APPTEMP";
pOutDatasetName1.WorkspaceName = pWorkspaceName;
pOutFeatureClassName1.FeatureType = esriFeatureType.esriFTSimple;
pOutFeatureClassName1.ShapeType = esriGeometryType.esriGeometryAny;
pOutFeatureClassName1.ShapeFieldName = "Shape";
IExportOperation pExportOperation = new ExportOperationClass();
pExportOperation.ExportFeatureClass(pInDatasetName1, null, pFeatureSelection1.SelectionSet, null, pOutFeatureClassName1, 0);
}
if (pEnsLayer != null)
{
pFeatureSelection2 = pEnsLayer as IFeatureSelection;
queryFilter.WhereClause = "BASIN_NAME = '" + m_Label + "'";
pDataset2 = pEnsLayer.FeatureClass as IDataset;
pFeatureSelection2.SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
pInFeatureClassName2 = pDataset2.FullName as IFeatureClassName;
pInDatasetName2 = pInFeatureClassName2 as IDatasetName;
pOutDatasetName2 = pOutFeatureClassName2 as IDatasetName;
pOutDatasetName2.Name = "ENSTEMP";
pOutDatasetName2.WorkspaceName = pWorkspaceName;
pOutFeatureClassName2.FeatureType = esriFeatureType.esriFTSimple;
pOutFeatureClassName2.ShapeType = esriGeometryType.esriGeometryAny;
pOutFeatureClassName2.ShapeFieldName = "Shape";
IExportOperation pExportOperation = new ExportOperationClass();
pExportOperation.ExportFeatureClass(pInDatasetName2, null, pFeatureSelection2.SelectionSet, null, pOutFeatureClassName2, 0);
}
IFeatureClass pAppFeatureClass = pFeatureWorkspace.OpenFeatureClass("APPTEMP");
IFeatureClass pEnsFeatureClass = pFeatureWorkspace.OpenFeatureClass("ENSTEMP");
//Execute clip.
Clip pClip = new Clip();
pClip.in_features = pAppFeatureClass;
pClip.clip_features = pEnsFeatureClass;
pClip.out_feature_class = "in_memory\\APP_ENS_OVERLAP";
Geoprocessor pGeoprocessor = new Geoprocessor();
pGeoprocessor.AddOutputsToMap = false;
pGeoprocessor.OverwriteOutput = true;
IGeoProcessorResult result = pGeoprocessor.Execute(pClip, null) as IGeoProcessorResult;
//Get the resulting intersection polygon.
IFeatureClass pOverlapEnsFeatureClass = pGeoprocessor.Open("in_memory\\APP_ENS_OVERLAP") as IFeatureClass;
pFeatureLayer.FeatureClass = pOverlapEnsFeatureClass;
IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
pFeatureSelection.SelectFeatures(null, esriSelectionResultEnum.esriSelectionResultNew, false);
ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet as ISelectionSet; //PROBLEM HERE
ICursor pCursor;
pSelectionSet.Search(null, true, out pCursor);
IFeatureCursor pFeatureCursor = pCursor as IFeatureCursor;
IFeature pIntersectFeature = pFeatureCursor.NextFeature();
IArea pIntersectArea = pIntersectFeature.Shape as IArea;
IArea pAppArea = pAppFeature.Shape as IArea;
IArea pEnsArea = pEnsFeature.Shape as IArea;
int appOverlap = Convert.ToInt32((pIntersectArea.Area / pAppArea.Area) * 100);
int ensOverlap = Convert.ToInt32((pIntersectArea.Area / pEnsArea.Area) * 100);
if (appOverlap > 5 || ensOverlap > 5)
return true;
else
return false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
//LogError(ex.StackTrace, ex.Message, "DetermineOverlapArea", null);
return false;
}
} Hi Carlos, I'm glad to hear you're making progress. Since you don't have the code to show why the Clip process didn't run, examine the Results information in ArcMap to find out what happened. Could it be that it's not overwriting "in_memory\APP_ENS_OVERLAP"? Have you set the Geoprocessor to overwrite outputs, either through the Geoprocessing Options dialog or by setting pGeoprocessor.OverwriteOutput = "true"
... View more
08-09-2011
07:45 AM
|
0
|
0
|
1285
|
|
POST
|
Ken, Thanks for sample code. Looking at your code, I got mine to work. Unfortunately, I am still having one issue. The methos below gets called from a loop. The first time the method gets called everything works fine. The second time however, the line below retuns null. GeoProcessorResult result = pGeoprocessor.Execute(pClip, null) as GeoProcessorResult; Any idea why this is happening? Thanks, Carlos public static bool DetermineOverlapArea3(IFeatureLayer pAppLayer, IFeatureLayer pEnsLayer,
IFeature pAppFeature, IFeature pEnsFeature)
{
try
{
IQueryFilter queryFilter = new QueryFilterClass();
IDataset pDataset1 = null;
IDataset pDataset2 = null;
IFeatureSelection pFeatureSelection1 = null;
IFeatureSelection pFeatureSelection2 = null;
IFeatureClassName pInFeatureClassName1 = new FeatureClassNameClass();
IFeatureClassName pInFeatureClassName2 = new FeatureClassNameClass();
IDatasetName pInDatasetName1 = null;
IDatasetName pInDatasetName2 = null;
IFeatureClassName pOutFeatureClassName1 = new FeatureClassNameClass();
IFeatureClassName pOutFeatureClassName2 = new FeatureClassNameClass();
IDatasetName pOutDatasetName1 = null;
IDatasetName pOutDatasetName2 = null;
IWorkspaceFactory pWorkspaceFactory = new InMemoryWorkspaceFactoryClass();
IFeatureLayer pFeatureLayer = new FeatureLayerClass();
IFeatureWorkspace pFeatureWorkspace = null;
IWorkspaceName pWorkspaceName = new WorkspaceNameClass();
pWorkspaceName = pWorkspaceFactory.Create("", "TEMP", null, 0);
IName pName = pWorkspaceName as IName;
IWorkspace pWorkspace = pName.Open() as IWorkspace;
pFeatureWorkspace = pWorkspace as IFeatureWorkspace;
if (pAppLayer != null)
{
pFeatureSelection1 = pAppLayer as IFeatureSelection;
queryFilter.WhereClause = "APP_NO = '" + m_AppNo + "'";
pDataset1 = pAppLayer.FeatureClass as IDataset;
pFeatureSelection1.SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
pInFeatureClassName1 = pDataset1.FullName as IFeatureClassName;
pInDatasetName1 = pInFeatureClassName1 as IDatasetName;
pOutDatasetName1 = pOutFeatureClassName1 as IDatasetName;
pOutDatasetName1.Name = "APPTEMP";
pOutDatasetName1.WorkspaceName = pWorkspaceName;
pOutFeatureClassName1.FeatureType = esriFeatureType.esriFTSimple;
pOutFeatureClassName1.ShapeType = esriGeometryType.esriGeometryAny;
pOutFeatureClassName1.ShapeFieldName = "Shape";
IExportOperation pExportOperation = new ExportOperationClass();
pExportOperation.ExportFeatureClass(pInDatasetName1, null, pFeatureSelection1.SelectionSet, null, pOutFeatureClassName1, 0);
}
if (pEnsLayer != null)
{
pFeatureSelection2 = pEnsLayer as IFeatureSelection;
queryFilter.WhereClause = "BASIN_NAME = '" + m_Label + "'";
pDataset2 = pEnsLayer.FeatureClass as IDataset;
pFeatureSelection2.SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
pInFeatureClassName2 = pDataset2.FullName as IFeatureClassName;
pInDatasetName2 = pInFeatureClassName2 as IDatasetName;
pOutDatasetName2 = pOutFeatureClassName2 as IDatasetName;
pOutDatasetName2.Name = "ENSTEMP";
pOutDatasetName2.WorkspaceName = pWorkspaceName;
pOutFeatureClassName2.FeatureType = esriFeatureType.esriFTSimple;
pOutFeatureClassName2.ShapeType = esriGeometryType.esriGeometryAny;
pOutFeatureClassName2.ShapeFieldName = "Shape";
IExportOperation pExportOperation = new ExportOperationClass();
pExportOperation.ExportFeatureClass(pInDatasetName2, null, pFeatureSelection2.SelectionSet, null, pOutFeatureClassName2, 0);
}
IFeatureClass pAppFeatureClass = pFeatureWorkspace.OpenFeatureClass("APPTEMP");
IFeatureClass pEnsFeatureClass = pFeatureWorkspace.OpenFeatureClass("ENSTEMP");
//Execute clip.
Clip pClip = new Clip();
pClip.in_features = pAppFeatureClass;
pClip.clip_features = pEnsFeatureClass;
pClip.out_feature_class = "in_memory\\APP_ENS_OVERLAP";
Geoprocessor pGeoprocessor = new Geoprocessor();
GeoProcessorResult result = pGeoprocessor.Execute(pClip, null) as GeoProcessorResult;
IGPValue pGPValue = result.GetOutput(0);
string InMemoryFeatureClass = string.Empty;
InMemoryFeatureClass = pGPValue.GetAsText();
//Get resulting feature class.
IGPUtilities pGPUtilities = new GPUtilities();
IFeatureClass pOverlapEnsFeatureClass = pGPUtilities.OpenFeatureClassFromString(InMemoryFeatureClass);
//Get the resulting intersection polygon.
pFeatureLayer.FeatureClass = pOverlapEnsFeatureClass;
IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
pFeatureSelection.SelectFeatures(null, esriSelectionResultEnum.esriSelectionResultNew, false);
ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet as ISelectionSet;
ICursor pCursor;
pSelectionSet.Search(null, true, out pCursor);
IFeatureCursor pFeatureCursor = pCursor as IFeatureCursor;
IFeature pIntersectFeature = pFeatureCursor.NextFeature();
IArea pIntersectArea = pIntersectFeature.Shape as IArea;
IArea pAppArea = pAppFeature.Shape as IArea;
IArea pEnsArea = pEnsFeature.Shape as IArea;
int appOverlap = Convert.ToInt32((pIntersectArea.Area / pAppArea.Area) * 100);
int ensOverlap = Convert.ToInt32((pIntersectArea.Area / pEnsArea.Area) * 100);
if (appOverlap > 5 || ensOverlap > 5)
return true;
else
return false;
}
catch (Exception ex)
{
LogError(ex.StackTrace, ex.Message, "DetermineOverlapArea", null);
return false;
}
}
... View more
08-08-2011
03:22 AM
|
0
|
0
|
1285
|
|
POST
|
Ken, Thanks for the reply. I saw something about that in the documentation but could not get it to work either. Do you have some sample code in any language I can look at that uses "in_memory"? Thanks for your time. Carlos I haven't tried using the IMemoryWorkSpaceFactory, but I have been able to use a geoprocessor process parameter like "in_memory\output"
... View more
08-04-2011
11:30 AM
|
0
|
0
|
1285
|
|
POST
|
Hi everyone, I am trying to use InMemoryWorkspaceFactory with the Geoprocessor in an attempt to improve a slow part of program. The code below runs fine if I use a file geodatabase so I know the logic is okay but as soon as I switch to trying to use an InMemoryWorkspaceFactory, the clip command produces no output and I don't get an error either. The second method is what I am using to list all layers in the workspace and it only list the in and clip layers, not the output. I've been trying stuff for two full days now and am out of ideas on what to try next. Thanks, Carlos
public static bool DetermineOverlapArea3(IFeatureLayer pAppLayer, IFeatureLayer pEnsLayer,
IFeature pAppFeature, IFeature pEnsFeature)
{
try
{
IQueryFilter queryFilter = new QueryFilterClass();
IDataset pDataset1 = null;
IDataset pDataset2 = null;
IFeatureSelection pFeatureSelection1 = null;
IFeatureSelection pFeatureSelection2 = null;
IFeatureClassName pInFeatureClassName1 = new FeatureClassNameClass();
IFeatureClassName pInFeatureClassName2 = new FeatureClassNameClass();
IDatasetName pInDatasetName1 = null;
IDatasetName pInDatasetName2 = null;
IFeatureClassName pOutFeatureClassName1 = new FeatureClassNameClass();
IFeatureClassName pOutFeatureClassName2 = new FeatureClassNameClass();
IDatasetName pOutDatasetName1 = null;
IDatasetName pOutDatasetName2 = null;
IWorkspaceFactory pWorkspaceFactory = new InMemoryWorkspaceFactoryClass();
IFeatureLayer pFeatureLayer = new FeatureLayerClass();
IFeatureWorkspace pFeatureWorkspace = null;
IWorkspaceName pWorkspaceName = new WorkspaceNameClass();
IFeatureClass pFeatureClass = null;
pWorkspaceName = pWorkspaceFactory.Create("", "TEMP", null, 0);
IName pName = pWorkspaceName as IName;
IWorkspace pWorkspace = pName.Open() as IWorkspace;
pFeatureWorkspace = pWorkspace as IFeatureWorkspace;
if (pAppLayer != null)
{
pFeatureSelection1 = pAppLayer as IFeatureSelection;
queryFilter.WhereClause = "APP_NO = '" + m_AppNo + "'";
pDataset1 = pAppLayer.FeatureClass as IDataset;
pFeatureSelection1.SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
pInFeatureClassName1 = pDataset1.FullName as IFeatureClassName;
pInDatasetName1 = pInFeatureClassName1 as IDatasetName;
pOutDatasetName1 = pOutFeatureClassName1 as IDatasetName;
pOutDatasetName1.Name = "APPTEMP";
pOutDatasetName1.WorkspaceName = pWorkspaceName;
pOutFeatureClassName1.FeatureType = esriFeatureType.esriFTSimple;
pOutFeatureClassName1.ShapeType = esriGeometryType.esriGeometryAny;
pOutFeatureClassName1.ShapeFieldName = "Shape";
IExportOperation pExportOperation = new ExportOperationClass();
pExportOperation.ExportFeatureClass(pInDatasetName1, null, pFeatureSelection1.SelectionSet, null, pOutFeatureClassName1, 0);
}
if (pEnsLayer != null)
{
pFeatureSelection2 = pEnsLayer as IFeatureSelection;
queryFilter.WhereClause = "BASIN_NAME = '" + m_Label + "'";
pDataset2 = pEnsLayer.FeatureClass as IDataset;
pFeatureSelection2.SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
pInFeatureClassName2 = pDataset2.FullName as IFeatureClassName;
pInDatasetName2 = pInFeatureClassName2 as IDatasetName;
pOutDatasetName2 = pOutFeatureClassName2 as IDatasetName;
pOutDatasetName2.Name = "ENSTEMP";
pOutDatasetName2.WorkspaceName = pWorkspaceName;
pOutFeatureClassName2.FeatureType = esriFeatureType.esriFTSimple;
pOutFeatureClassName2.ShapeType = esriGeometryType.esriGeometryAny;
pOutFeatureClassName2.ShapeFieldName = "Shape";
IExportOperation pExportOperation = new ExportOperationClass();
pExportOperation.ExportFeatureClass(pInDatasetName2, null, pFeatureSelection2.SelectionSet, null, pOutFeatureClassName2, 0);
}
ESRI.ArcGIS.AnalysisTools.Clip pClip = new ESRI.ArcGIS.AnalysisTools.Clip();
pClip.in_features = pWorkspace + "APPTEMP";
pClip.clip_features = pWorkspace + "ENSTEMP";
pClip.out_feature_class = pWorkspace + "APP_ENS_OVERLAP";
ITrackCancel pTrackCancel = new CancelTrackerClass();
pTrackCancel.CancelOnClick = false;
pTrackCancel.CancelOnKeyPress = true;
ESRI.ArcGIS.Geoprocessor.Geoprocessor pGeoprocessor = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();
pGeoprocessor.Execute(pClip, pTrackCancel);
//Get the resulting intersection polygon.
pFeatureClass = pFeatureWorkspace.OpenFeatureClass("APP_ENS_OVERLAP");
pFeatureLayer.FeatureClass = pFeatureClass;
IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
pFeatureSelection.SelectFeatures(null, esriSelectionResultEnum.esriSelectionResultNew, false);
ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet as ISelectionSet;
ICursor pCursor;
pSelectionSet.Search(null, true, out pCursor);
IFeatureCursor pFeatureCursor = pCursor as IFeatureCursor;
IFeature pIntersectFeature = pFeatureCursor.NextFeature();
IArea pIntersectArea = pIntersectFeature.Shape as IArea;
IArea pAppArea = pAppFeature.Shape as IArea;
IArea pEnsArea = pEnsFeature.Shape as IArea;
int appOverlap = Convert.ToInt32((pIntersectArea.Area / pAppArea.Area) * 100);
int ensOverlap = Convert.ToInt32((pIntersectArea.Area / pEnsArea.Area) * 100);
if (appOverlap > 5 || ensOverlap > 5)
return true;
else
return false;
}
catch (Exception ex)
{
LogError(ex.StackTrace, ex.Message, "DetermineOverlapArea", null);
return false;
}
} IEnumDataset pEnumDataset = pWorkspace.get_Datasets(esriDatasetType.esriDTFeatureClass) as IEnumDataset;
IDataset pDataset = pEnumDataset.Next();
while (pDataset != null)
{
MessageBox.Show(pDataset.Name);
pDataset = pEnumDataset.Next();
}
... View more
08-04-2011
05:46 AM
|
0
|
8
|
1832
|
|
POST
|
Neil, Alexander, Sorry for the late reply. I was out Thursday afternoon and all day Friday. Neil, you are correct, the bottleneck is the Intersect command in the DeterimeOverlapArea method. I'm trying to figure out what I can use in it's place that might be faster. Alexander, the Convert.ToInt32 is very fast so that part of the code is okay although I will try your suggestion. Every little bit of speed increase helps. Carlos
... View more
08-01-2011
03:11 AM
|
0
|
0
|
1259
|
|
POST
|
Aparently, I messed up doing the first test because when I repeated them later trying some of Neil's suggestion, the code took less than a minute. The bottleneck is definitely between GetAppInfo and DetermineOverlapArea. The biggest bottleneck seems to be DetermineOverlapArea. I've been trying alternative code all day and get the same slow results.
... View more
07-28-2011
09:05 AM
|
0
|
0
|
1259
|
|
POST
|
Neil, I tried your suggestions for speeding up method DetermineOverlapArea and it's just as slow as before. I tried passing in the geometries both as polygons as well as geometries and there is no improvement at all. It takes 10 minutes to get through 5 records. A few things to try: First, a method should only take what it really needs as parameters. In this case, you don't really need 2 features, you need 2 polygons. So I would modify the method signature to this: public static bool DetermineOverlapArea(IPolygon polygon1, IPolygon polygon2) When you call the method, pass in the feature geometries cast as polygons. Use ShapeCopy instead of Shape because you don't want your method altering the feature geometries. Try skipping the geomtry simplification. The general idea here is that an unmodified feature geometry from a feature class will already be simple. Remove the if/else block at the end and replace it with: return (appOverlap > 5 || ensOverlap > 5); Probably not much time savings there but every bit counts.
... View more
07-28-2011
05:56 AM
|
0
|
0
|
1852
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 02-11-2016 06:06 AM | |
| 1 | 08-07-2015 10:13 AM | |
| 2 | 06-29-2015 12:45 PM |
| Online Status |
Offline
|
| Date Last Visited |
11-11-2020
02:23 AM
|