POST
|
I'm doing a copy of a geodatabase and I want to remove the layers I do not care about. Then, I'm removing some features from the remaining layer in such a way that the IDs won't change. (Removing seems to be the right option.) Alternate: How can I create a geodatabase with one layer from another geodatabase or from a layer from the current view (with selected features, or using a QueryFilter). I need to conserve the IDs (and all other fields.)
... View more
10-19-2016
11:14 AM
|
1
|
0
|
586
|
POST
|
I cannot get right functionality in ArcGIS Pro for a MessageBox. I'm using: using MessageBox = ArcGIS.Desktop.Framework.Dialogs.MessageBox;
but this is what I get: Issues: 1.The icon is vertically center-aligned - should be top! in this screen, I can see only half of it. 2. There is no scroll bar and the message box cannot be resized. 3. Content cannot be highlighted and/or copied to the Clipboard. 4. (Title is center-aligned instead of left-aligned.) I could use the System.Windows.Forms.MessageBox instead, but this one is not modal and usually ends up under the main ArcGIS Pro window! Is there another name space containing MessageBox more suitable for ArcGIS Pro? (Is it such namespace suitable also for various dialogs?)
... View more
10-12-2016
02:01 PM
|
1
|
2
|
2360
|
POST
|
Thanks - it works for me too! Great Response! Still a small issue but not related to my issues: The colors of the sliders above look weird: shouldn't be red - something like red, green - something like green, and blue - something like blue?
... View more
09-30-2016
01:10 PM
|
0
|
0
|
1027
|
POST
|
Hi Charles, I see now: trans is 50.0 instead of 255! Tx,
... View more
09-30-2016
01:00 PM
|
0
|
0
|
1027
|
POST
|
No, is not: From line 20 to line 26 I,m explicitly define the stoke with black color. See, the thing is that this is a template used in line 31, that together with the colorRamp instance form in line 51 the Unique...Def. Now: if we create make the line red: symbol = SymbolFactory.ConstructPolygonSymbol(
ColorFactory.GreyRGB, SimpleFillStyle.Solid,
new CIMSolidStroke()
{
Width = 1.5,
Color = CIMColor.CreateRGBColor(255, 0, 0, 127)
}); When running the application, we get: Where we see that the line was correctly defined, but the corresponding checkbox was not enabled. (And no: it is red but not semitransparent!) Note that ConstructPolygonSymbol has another constructor which takes, instead of the first two parameters, a Fill (something) type, in the same way as the stroke. When using that, the fill symbol comes also unchecked! (On my wish list there are also: 1. Use directly (some sort of) UniqueValuesItems instead of colorRamp and symbolTemplate, as I've mentioned in the second line of my question. 2. Be able to customize the color of the stroke as well, 3. And, as I've already mentioned, make the fill transparent (if possible, the stroke as well.) #2 and the () in 3# are optional, but without the rest - is not going to work... )
... View more
09-30-2016
12:07 PM
|
0
|
1
|
1017
|
POST
|
I know by hart that snippet since it is the only one that shows something about creating an UniqueValueRender. However it is limited to MapPoints that do not require transparency, not even color ramps! More details about how I'm using that code - in my other question, here: https://community.esri.com/message/638051-how-to-create-an-uniquevaluerenderer
... View more
09-29-2016
01:38 PM
|
0
|
5
|
1027
|
POST
|
I would prefer the method for ArcGIS Desktop described here: Symbols and renderers—ArcGIS Runtime SDK for .NET | ArcGIS for Developers But I cannot make it work in ArcGis PRO. Instead I use the following code:
var uniqueValueRendererDef = GetUniqueValueRendererDef();
var uniqueValueRenderer = (CIMUniqueValueRenderer)deltaLayer.CreateRenderer(uniqueValueRendererDef);
var classes = uniqueValueRenderer.Groups[0].Classes;
uniqueValueRendererDef = GetUniqueValueRendererDef(classes);
uniqueValueRenderer = (CIMUniqueValueRenderer)deltaLayer.CreateRenderer(uniqueValueRendererDef);
deltaLayer.SetRenderer(uniqueValueRenderer);
...
private UniqueValueRendererDefinition GetUniqueValueRendererDef(CIMUniqueValueClass[] classes = null)
{
string[] fields = { Model.DbFieldOperation.Key }; //field to be used to retrieve unique values
CIMMultiLayerSymbol symbol = null;
switch (DeltaLayer.ShapeType)
{
...
case esriGeometryType.esriGeometryPolygon:
symbol = SymbolFactory.ConstructPolygonSymbol(
ColorFactory.GreyRGB, SimpleFillStyle.Solid, new CIMSolidStroke()
{
Width = 3.0,
Color = //CIMColor.CreateRGBColor(0, 0, 0, 127)
ColorFactory.BlackRGB
});
break;
...
}
var symbolTemplate = symbol.MakeSymbolReference();
var colorRamp = new CIMFixedColorRamp();
if (classes == null)
{
colorRamp.Colors = new[] { ColorFactory.RedRGB, ColorFactory.GreenRGB };
}
else
{
var colors = new List();
foreach (var cls in classes)
{
switch (cls.Label)
{
...
case "DELETE":
colors.Add(DeltaLayer.ShapeType == esriGeometryType.esriGeometryPolygon
? ColorFactory.CreateRGBColor(255, 0, 0, 128) : ColorFactory.RedRGB);
break;
default:
colors.Add(ColorFactory.GreyRGB);
break;
}
}
colorRamp.Colors = colors.ToArray();
}
var uniqueValueRendererDef = new UniqueValueRendererDefinition(fields, symbolTemplate, colorRamp);
return uniqueValueRendererDef;
}
Explanation: The first call to GetUniqueValueRendererDef() in line 2 is to obtain the unique values (in line 4.) The second call in line 5 produces the desired ColorRamp. The efect was described in my question: How to use ColorFactory to produce transparent colors for a ColorRamp? I cannot simply produce an universal color ramp with 3 (or more) colors because the renter allocates for the second and subsequent values random colors from the ramp when the ramp contains more colors than unique values! This is inconvenient - I would call it a bug! Now, the real problem in this post: For Polynomial Layers I need transparent symbols - this I have already described in the above question. However, in line 21 I have also asked for a stroke (solid black - although my first preference was transparent as well) 3 units tick. Not only the stroke does not come, but neither can be added with the symbol editor! Look at the effect when using a SimpleFillStyle.Vertical filling (line 21) The cyan rectangle is the selected polygon, but there are 2 polygons there and without stroke line it is impossible to make the difference. Obviously, any king of filling won't replace the transparency on the symbol, but missing strokes makes thinks even worse! The Format Polygon Symbol dialog shoes: The solid stroke checkbox came unchecked - why? When manually checking it, I can see what I want! (Much better!)
... View more
09-29-2016
09:19 AM
|
0
|
3
|
2403
|
POST
|
This is my code: var colorRamp = new CIMFixedColorRamp();
var colors = new List();
foreach (var cls in classes)
{
switch (cls.Label)
{
case "INSERT":
colors.Add(DeltaLayer.ShapeType == esriGeometryType.esriGeometryPolygon
? ColorFactory.CreateRGBColor(0, 255, 0, 128) : ColorFactory.GreenRGB);
break;
case "DELETE":
colors.Add(DeltaLayer.ShapeType == esriGeometryType.esriGeometryPolygon
? ColorFactory.CreateRGBColor(255, 0, 0, 128) : ColorFactory.RedRGB);
break;
default:
colors.Add(ColorFactory.GreyRGB);
break;
}
}
colorRamp.Colors = colors.ToArray();
The goal is to produce an UniqueValueRenderer that will allow overlapping polygons to show distinct by using transparent colors. As after line 20 the colors in the ramp looks like having some transparency: The result in the property editor (and on the Map) does not reflect this: Beside, the sliders near the Red and Blue value numeric boxes are very confusing: shouldn't they be read and blue?! What is this?! Note: the Transparency can be adjusted from this editor proving that the UniqueValueRender supports transparent colors, but it does not come as such from the code!
... View more
09-29-2016
08:28 AM
|
1
|
7
|
1754
|
POST
|
Unfortunately, the solution with AddOverlay is not a good fit: AddOverlay waits for the map to be not busy (long time) while the previous solution was putting everything on the map before finishing updating the base map! I have reverted everything and used your previous suggestion...
... View more
08-02-2016
06:07 PM
|
0
|
0
|
967
|
POST
|
Trying your solution now, which is cleaner - I did not know about AddOverlay method! (How do you remove the geometries added like that!?) Working from home today, - looks a lot slowser because the map remains busy after each zomm for a couple seconds. I had the feg that the previous method (using FeatureLayers) was rendering my symbols before clearing the busy flag... I have to come back to check, or to go to the office to have faster connection... (I also have to stop now for a couple hours...)
... View more
08-02-2016
01:34 PM
|
0
|
2
|
967
|
POST
|
Thank you, However I got so many issues that I've consider a complete different approach: I've created features layers in the project's gdb, added symbollogy of each type (I need two types - so two feature layers, each with its own symbollogy - the easiest approach,) and I'm adding my buffers as geometries (with an EditOperation.) Before that, I've tried everything and got something working (sorry, I don't have the code anymore.) My extension explores a collection of features (roads) that can be paired (Delete segment with Insert segment) automatically - testing the end points and the middle point in a buffer. I'm showing the buffers for visual feedback. When the solution using ExecToolAsync was ready (with lot of delays, flickering, dudes, etc.) I was able to explore max 12-20 features, after them ArcGIS Pro was blocking in a dead-lock (no error, no message, nothing - just waiting forever.) It was not the first issue with ExecToolAsync, so I've decided to stop wasting time and did the research for the above solution. Even so, I'm still using Geoprocessing.ExecuteToolAsync("management.CreateFeatureClass" once I'm starting a new project and is not quite working as expected: private async void AddSketchLayers()
{
PointMatchLayer = await AddSketchLayer(Model.LayerPointMatch, true);
PointEmptyLayer = await AddSketchLayer(Model.LayerPointEmpty, false);
}
private async Task<FeatureLayer> AddSketchLayer(string layerName, bool fill)
{
var layerNames = DeltaMap.Map.Layers.Select(l => l.Name).ToArray();
if (layerNames.Contains(layerName))
{
return DeltaMap.Map.Layers.FirstOrDefault(l => l.Name == layerName) as FeatureLayer;
}
SetBusy($"Create {layerName}...");
try
{
var outPath = Project.Current.DefaultGeodatabasePath;
var result = await QueuedTask.Run(async () =>
{
//var workspaceName = $@"in_memory\{layerName}";
var parameters = Geoprocessing.MakeValueArray(
outPath, layerName, "Polygon", null, "No","No", DeltaLayer.Map.SpatialReference.Wkid);
//var env = Geoprocessing.MakeEnvironmentArray(workspace: workspaceName);
var cts = new CancellationTokenSource();
await Geoprocessing.ExecuteToolAsync("management.CreateFeatureClass",
parameters, null, cts.Token, (eventName, o) =>
{
switch (eventName)
{
case "OnValidate":
if (((IGPMessage[])o).Any(it => it.Type == GPMessageType.Warning ||
it.Type == GPMessageType.Error))
{
{
var errorsOrWarnings =
((IGPMessage[])o).Where(it => it.Type == GPMessageType.Error).ToArray();
if (errorsOrWarnings.Any())
{
var e = errorsOrWarnings.Select(err => err.Text).ToArray();
MessageBox.Show(string.Join(@"
", e));
cts.Cancel();
}
}
}
break;
}
});
var layer = DeltaMap.Map.Layers.FirstOrDefault(l => l.Name == layerName) as FeatureLayer;
if (layer == null)
{
layer = LayerFactory.CreateFeatureLayer(
new Uri($@"{outPath}\{layerName}", UriKind.Relative),
DeltaMap.Map);
}
if (layer != null)
{
layer.SetDisplayCacheType(DisplayCacheType.None);
layer.SetSnappable(false);
layer.SetEditable(false);
layer.SetSelectable(false);
layer.SetShowPopups(false);
var rendererDefinition = new SimpleRendererDefinition
{
SymbolTemplate = SymbolFactory.ConstructPolygonSymbol(
fill
? ColorFactory.CreateRGBColor(162, 80, 255, 90)
: ColorFactory.CreateRGBColor(255, 88, 100, 90),
fill
? SimpleFillStyle.Solid
: SimpleFillStyle.Null,
new CIMSolidStroke
{
Color = fill
? ColorFactory.CreateRGBColor(162, 80, 255, 127)
: ColorFactory.CreateRGBColor(255, 88, 100, 127),
Width = 1,
Enable = true
}).MakeSymbolReference()
};
var simpleValueRenderer = (CIMSimpleRenderer)(layer.CreateRenderer(rendererDefinition));
layer.SetRenderer(simpleValueRenderer);
}
return layer;
});
return result;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
return null;
} See lines 56 to 64. Note that I need two Feature Layer, so I call the method AddSketchLayer twice in lines 3 and 4. The test in line 58 is for the first call, the second call adds the layer to the map directly (line(56,) totally unexpected! If I'll have more issue with this code, I'll try to replace the call to ExecToolAsync from line 30 with something more natively... ExecuteToolAsync
... View more
08-02-2016
12:40 PM
|
0
|
1
|
966
|
POST
|
This is what the extension does: Basically, given a road segment, it tries to match another one with complementary operation INSERT/DELETE. The test is done in three points - two at segment ends and one somewhere in the middle. The calculation is always correct and displayed on the bottom of the grid. The display is done only for the user convenience and repeats the buffering with the tool mentioned before. The buffer is about 1/20 of the segment road, and the segment road length is consistent with small streets in an average city. (The units are in Degrees - I would have prefer them in meters to be able to put a cap, but since it is not a real requirement, I can operate also in degrees. The value is something 10^-5, so not very comprehensive...) The picture above is one that succeeds after about 8 trials. I can repeat the attempt clicking the button "Automatic Pairing" on the Delete header. It gets a few seconds to get the disks/circle in some random colors and a few more to change in these standard colors depicted there. But all the previous trials came with no circles, sometimes only with the two filled ones, some other times only with the empty one. When I have three match points - there is only one call to ExecToolAsinc (l2 in the second code block above, is null.) In that situation I can get the picture ready most of the times, but there are also situations when I have to repeat. (Before doing all that, I'm also deleting all previous disks, but I have commented that procedure (line 13) during tests, and it has no effect: public async Task<bool> ClearBufferLayers()
{
AutomaticMessage = null;
AutomaticPossiblePair = null;
await QueuedTask.Run(() =>
{
return DeltaLayer.Map.Layers.Where(l =>
{
var b = l as FeatureLayer;
return (b != null) && (b.LabelClasses[0].WhereClause == "[BUFF_DIST]");
});
}).ContinueWith(async t => await QueuedTask.Run(() => DeltaLayer.Map.RemoveLayers(t.Result)));
//await QueuedTask.Run(() => DeltaLayer.Map.RemoveLayers(buffLayers));
return true;
} ) I'm using ExecToolAsync because I cannot draw directly on the map. ArcGis Pro does not support GraphicsLayers (or does it?) and I'm not able to create a FeatureLayer on the fly. This is the code I attempt to run a new feature layer in the default geodatabase: private async Task AddSketchLayer(string layerName, bool fill)
{
var uri = new Uri($@"{Project.Current.DefaultGeodatabasePath}\{layerName}", UriKind.Absolute);
try
{
var f = await QueuedTask.Run(() => LayerFactory.CreateLayer(uri, DeltaMap.Map));
}
catch
{
}
} But it fails! The error is System.ArgumentException, the Exception message is {"Failed to create layer from C:\\Users\\htudosie\\Documents\\ArcGIS\\Projects\\MyProject1\\MyProject1.gdb\\PointMatchLayer."} There is no other detail or tip on how I can fix it. Being able to build that feature layer and adding a render, I would get rid of ExecToolAsinc. I already have the buffer shapes...
... View more
07-29-2016
06:58 AM
|
0
|
1
|
967
|
POST
|
Maybe I'm doing wrong in ArcGIS Pro, because I've started the first application/Extension with the old good habits from pure WPF applications. But usually, you connect the View model in XAML like this: <Grid x:Name="main" >
<Grid.DataContext>
<local:GfxViewModel/>
</Grid.DataContext> (Where Grid may be any control in the page, not necessary the root, and the ViewModel may not be the main one handeled by the DockPaneManager.) This approach, with proper techniques, let the page function in DesignMode as well using the Inversion Of Control pattern (somehow, injecting a corresponding model for RealTime, another for DesignMode and some more for unit tests...)) The problem is that if you associate the same ViewModel with another page in this way, each page creates its own instance, so the data you want to share is different in each instance. What the above code references in line 3 is actually the parameter-less constructor of the ViewModel. You cannot add a parameter, refer a Singleton or a a static reference (although a static resource does the job...) This is where the VMLocator comes. It is actually a static reference that manages VMs. It needs however a place where to instantiate its Singleton. DockPanelManager is not a very good place, because you may need the VM instance in a Tool as well for example! GalaSoft's MVVM Light may instantiate singletons managed by the static resource VMLocator in a top page named APP.XAML. VMLocator is a very complex piece of code - I dare not reproduce it, mostly because of the testing involved. It is a manager that can manage multiple VMs, singletons or not. I already have a solution in the code behind, but I ask for a professional solution if somebody already have put it in ArcGIS Pro. In my extension I have a DockingPanel that handle the main work with the above VM. I open it with a Ribbon Button. I have another DockPanel that I open with another button (in a split of another ribbon button) that displays a Pie Chart (the beginning of a Dashboard,) with the data from the first Panel's VM. Users may activate these buttons in any order, but obviously one of them is wrong. My code behind in the Chart Panel check the instance of the Main Panel and give up if was not instantiated: the panel comes blank. Could come better if it could make the instance first: could display a pie with four equal sectors (Eventually a message) which are the defaults of the DataSource. Will cange as soon as the VM will get notifications (Property Changed) from the first page. But this solution would require instantiating the (same) VM of the Working Panel also in code. This makes the Design Time complicated... (And I don't have a general-enough place where to put the singleton.) (Blocking the button of the Pie Panel until the Working panel opens also works, but then the ToolTip of the button - not mentioning the panel itself - won't come and I'll have to write a manual or help, which makes the User Experience gross...) Note that instantiating VMs in the code behind, which is technically the View, breaks the MVVM pattern, making the design difficult and the testing incomplete! Note also that a DockpaneViewModel is not exactly a ViewModel: it contains an internal static class for the button to open it, with override methods, which you have to trust - not to test...
... View more
07-28-2016
05:07 PM
|
0
|
1
|
1130
|
POST
|
I'm using this work around: var v1 = await QueuedTask.Run(() => Geoprocessing.MakeValueArray(l1, null, units));
await Geoprocessing.ExecuteToolAsync("analysis.Buffer", v1).ContinueWith(async t =>
{
var fillBuffLayer = DeltaLayer.Map.Layers.Where(l =>
{
var b = l as FeatureLayer;
return (b != null) && (b.LabelClasses[0].WhereClause == "[BUFF_DIST]");
}).FirstOrDefault();
var buffLayer1 = (FeatureLayer)fillBuffLayer;
if (buffLayer1 != null)
{
var simpleValueRenderer =
(CIMSimpleRenderer)buffLayer1.CreateRenderer(BufferFillRendererDefinition));
buffLayer1.SetRenderer(simpleValueRenderer);
} However it takes long time to execute and flickers ugly... The second issue I face: the above code continue like this: if (l2 != null)
{
var v2 = await QueuedTask.Run(() => Geoprocessing.MakeValueArray(l2, null, units));
await Geoprocessing.ExecuteToolAsync("analysis.Buffer", v2);
var emptyBuffLayer = DeltaLayer.Map.Layers.Where(l =>
{
var b = l as FeatureLayer;
return (b != null) && !Equals(b, buffLayer1) && (b.LabelClasses[0].WhereClause == "[BUFF_DIST]");
}).FirstOrDefault();
var buffLayer2 = (FeatureLayer)emptyBuffLayer;
if (buffLayer2 != null)
{
var simpleValueRenderer =
(CIMSimpleRenderer)(buffLayer2.CreateRenderer(BufferEmptyRendererDefinition));
buffLayer2.SetRenderer(simpleValueRenderer);
} and it is called after a Select and a Zoom to a feature which contains the points from the arrays l1 and l2. With or without this code, after Select/Zoom, the map remains busy for a long lime (like in 5-10 seconds - why?!) ...Most of the times it fails either the points in l1 or l2 (IReadOnlyCollection<object>), or both, or fails to change the renter. However, some times (quite seldom) it works well... Would it be because of the busy time on the mapView? (And - third: Intellisesnse reports closures for l1, l2 and this on both ContinueWith...)
... View more
07-28-2016
08:18 AM
|
0
|
8
|
2412
|
POST
|
I need a VM instantiated by whatever Tool/Button was activated firstly, but shared by the other tools as well.
... View more
07-26-2016
07:05 AM
|
0
|
3
|
3548
|
Title | Kudos | Posted |
---|---|---|
1 | 10-12-2016 02:01 PM | |
1 | 10-17-2017 12:16 PM | |
1 | 11-26-2015 07:47 PM | |
1 | 03-02-2018 11:28 AM | |
1 | 12-01-2015 02:07 PM |
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:23 AM
|