Hi!
I created non-geo map view and placed 1000 of points.
I want to cluster them using FeatureReduction.
When i start application i can see:
But when I click "draw cluster" i got an error:
Pulse Failed: Invalid argument: Not a GCS or PCS
Here is my MainWindow.xaml.cs:
using Esri.ArcGISRuntime.ArcGISServices;
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Mapping.Labeling;
using Esri.ArcGISRuntime.Mapping.Popups;
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.Reduction;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.UI;
using Esri.ArcGISRuntime.UI.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Clusters
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private FeatureLayer _layer;
GraphicsOverlay _theGraphicsOverlays;
GraphicsOverlay _theGraphicsOverlaysNon;
private ClusteringFeatureReduction _clusteringFeatureReduction;
public MainWindow()
{
InitializeComponent();
_ = Initialize();
}
bool generatePoints = true;
int countPoints = 200;
void addIncidents()
{
_theGraphicsOverlays = new GraphicsOverlay();
// Get the graphic collection from the graphics overlay.
GraphicCollection theGraphicCollection = _theGraphicsOverlays.Graphics;
SimpleMarkerSymbol theSimpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Square, System.Drawing.Color.Red, 28);
theSimpleMarkerSymbol.Outline = new SimpleLineSymbol();
theSimpleMarkerSymbol.Outline.Color = System.Drawing.Color.Black;
List<Graphic> mapPoints = new List<Graphic>();
List<Graphic> mapPoints1 = new List<Graphic>();
if (generatePoints)
{
Random random = new Random();
for (int i = 0; i < countPoints; i++)
{
double x = random.Next(0, 2000); // Replace 10000 with your desired range for X coordinates
double y = random.Next(-1000, 0); // Replace 10000 with your desired range for Y coordinates
double z = 0; // If you need random Z values, generate them here
MapPoint point = new MapPoint(x, y, z);
var textSymbol = new TextSymbol
{
Text = $"{x},{y}",
Color = System.Drawing.Color.Black,
HaloColor = System.Drawing.Color.White,
HaloWidth = 2,
Size = 4,
VerticalAlignment = Esri.ArcGISRuntime.Symbology.VerticalAlignment.Middle,
HorizontalAlignment = Esri.ArcGISRuntime.Symbology.HorizontalAlignment.Center
};
var compositeSymbol = new CompositeSymbol
{
Symbols = { theSimpleMarkerSymbol, textSymbol }
};
mapPoints.Add(new Graphic(point, compositeSymbol));
mapPoints1.Add(new Graphic(point, compositeSymbol));
}
}
theGraphicCollection.AddRange(mapPoints);
MyMapViewNonGeo.GraphicsOverlays.Add(_theGraphicsOverlays);
}
private async void LoadRaster(RasterLayer myRasterLayer)
{
await myRasterLayer.LoadAsync();
await MyMapViewNonGeo.SetViewpointGeometryAsync(myRasterLayer.FullExtent);
}
private async Task Initialize()
{
//MyMapView.Map = new Map(SpatialReferences.WebMercator);
MyMapViewNonGeo.Map = new Map();
string filename = System.IO.Path.GetFullPath(@"C:\Files\QuartzTest\QuartzTest\NonGeo\worldmap-countries-hd.jpg");
// Create the layer
RasterLayer imageLayer = new RasterLayer(filename);
LoadRaster(imageLayer);
MyMapViewNonGeo.Map.Basemap.BaseLayers.Add(imageLayer);
DrawClustersButton.IsEnabled = true;
addIncidents();
}
private void CreateCustomFeatureReduction()
{
try
{
// Create a class breaks renderer to apply to the custom feature reduction.
ClassBreaksRenderer classBreaksRenderer = new ClassBreaksRenderer();
classBreaksRenderer.DefaultSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Diamond, System.Drawing.Color.White, 24)
{
Outline = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, System.Drawing.Color.FromArgb(0, 122, 204), 2)
};
_clusteringFeatureReduction = new ClusteringFeatureReduction(classBreaksRenderer);
// Set the feature reduction for the layer.
//_layer.FeatureReduction = _clusteringFeatureReduction;
var incidents = MyMapViewNonGeo.GraphicsOverlays.First();
incidents.FeatureReduction = _clusteringFeatureReduction;
var simpleLabelExpression = new SimpleLabelExpression("[cluster_count]");
var textSymbol = new TextSymbol()
{
Color = System.Drawing.Color.Black,
Size = 15,
HaloColor = System.Drawing.Color.White,
HaloWidth = 2
};
var labelDefinition = new LabelDefinition(simpleLabelExpression, textSymbol) { Placement = LabelingPlacement.PointCenterCenter };
// Add the label definition to the feature reduction.
//_clusteringFeatureReduction.LabelDefinitions.Add(labelDefinition);
// Populate the cluster radius and max scale pickers with default values.
List<double> items = new List<double> { 0, 1, 2, 3, 4, 5, 6, 10, 15, 30, 45, 60, 75, 90, 100,200,300, 1000 };
ClusterRadiusPicker.ItemsSource = items;
// Set initial picker values.
// Note that the default value for cluster radius is 60.
// Increasing the cluster radius increases the number of features that are grouped together into a cluster.
ClusterRadiusPicker.SelectedValue = _clusteringFeatureReduction.Radius;
}
catch (Exception ex)
{
}
}
#region EventHandlers
private void DisplayLabelsCheckBox_Checked(object sender, RoutedEventArgs e)
{
if ((bool)(sender as CheckBox).IsChecked)
{
// Create a label definition with a simple label expression.
var simpleLabelExpression = new SimpleLabelExpression("[cluster_count]");
var textSymbol = new TextSymbol() { Color = System.Drawing.Color.Black,
Size = 15,
HaloColor = System.Drawing.Color.White,
HaloWidth = 2
};
var labelDefinition = new LabelDefinition(simpleLabelExpression, textSymbol) { Placement = LabelingPlacement.PointCenterCenter };
// Add the label definition to the feature reduction.
_clusteringFeatureReduction?.LabelDefinitions.Add(labelDefinition);
}
else
{
_clusteringFeatureReduction.LabelDefinitions.Clear();
}
}
// When a new picker item is selected, update the feature reduction cluster radius.
private void ClusterRadiusPicker_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_layer != null)
{
((ClusteringFeatureReduction)_layer.FeatureReduction).Radius = (double)ClusterRadiusPicker.SelectedItem;
}
if (_theGraphicsOverlaysNon != null)
{
((ClusteringFeatureReduction)_theGraphicsOverlaysNon.FeatureReduction).Radius = (double)ClusterRadiusPicker.SelectedItem;
}
}
private void DrawClustersButton_Clicked(object sender, RoutedEventArgs e)
{
try
{
// Create a new clustering feature reduction.
CreateCustomFeatureReduction();
// Show the feature reduction's clustering options.
ClusteringOptions.Visibility = Visibility.Visible;
// Hide the draw clusters button.
DrawClustersButton.Visibility = Visibility.Collapsed;
}
catch(Exception ex)
{
}
}
// Hide and nullify the opened popup when user left clicks.
private void PopupBackground_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
PopupBackground.Visibility = Visibility.Collapsed;
//PopupViewer.Popup = null;
}
#endregion EventHandlers
}
}
Here is MainWindow.xaml
<Window x:Class="Clusters.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Clusters"
xmlns:quartz="http://schemas.esri.com/arcgis/runtime/2013"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<quartz:MapView x:Name="MyMapViewNonGeo" />
<Border Width="auto"
Height="auto">
<StackPanel Orientation="Vertical">
<Button x:Name="DrawClustersButton"
Padding="5"
HorizontalAlignment="Center"
Click="DrawClustersButton_Clicked"
Content="Draw clusters"
IsEnabled="False" />
<Grid x:Name="ClusteringOptions" Visibility="Collapsed">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2"
Padding="5"
HorizontalAlignment="Center"
FontSize="16"
FontWeight="Bold"
Text="Clustering Properties" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Padding="5"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontWeight="Bold"
Text="Display labels:" />
<CheckBox x:Name="DisplayLabelsCheckBox"
Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center"
Checked="DisplayLabelsCheckBox_Checked"
IsChecked="true"
Unchecked="DisplayLabelsCheckBox_Checked" />
<TextBlock Grid.Row="2"
Grid.Column="0"
Padding="5"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<Run FontWeight="Bold" Text="Cluster radius:" />
<Run Text="{Binding ElementName=ClusterRadiusSlider, Path=Value, Mode=OneWay, StringFormat=n0}" />
</TextBlock>
<ComboBox x:Name="ClusterRadiusPicker"
Grid.Row="2"
Grid.Column="1"
Width="75"
HorizontalAlignment="Left"
VerticalAlignment="Center"
SelectionChanged="ClusterRadiusPicker_SelectionChanged" />
<TextBlock Grid.Row="3"
Grid.Column="0"
Padding="5"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<Run FontWeight="Bold" Text="Maximum map scale:" />
<Run Text="{Binding ElementName=MaxScaleSlider, Path=Value, Mode=OneWay, StringFormat=n0}" />
</TextBlock>
<TextBlock Grid.Row="4"
Grid.Column="0"
Grid.ColumnSpan="2"
Padding="5"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Run FontWeight="Bold" Text="Current map scale: " />
<Run Text="1:" />
<Run Text="{Binding ElementName=MyMapView, Path=MapScale, Mode=OneWay, StringFormat=n0}" />
</TextBlock>
</Grid>
</StackPanel>
</Border>
<TextBlock x:Name="DistanceTextBlock" Foreground="Black"
HorizontalAlignment="Left" VerticalAlignment="Center"
Text="Distance between points: " TextWrapping="Wrap" FontWeight="Bold" Margin="28,10,0,395" Height="auto" Width="266"/>
<Grid x:Name="PopupBackground"
Background="#AA333333"
MouseLeftButtonDown="PopupBackground_MouseLeftButtonDown"
Visibility="Collapsed">
<Border HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="White">
<!--<quartz:PopupViewer x:Name="PopupViewer"
MaxWidth="400"
MaxHeight="400"
Margin="5"
Padding="5" />-->
</Border>
</Grid>
</Grid>
</Window>
My question is do you support clustering at all for Non geo maps, if yes, what should i change to have it working?
Thanks
Could you try and assign a SpatialReference to the MapPoints you're creating and let me know if that helps.
Hi!
Thanks for the reply.
So, when i added spatial reference WGS84 (on line 10):
if (generatePoints)
{
Random random = new Random();
for (int i = 0; i < countPoints; i++)
{
double x = random.Next(0, 2000); // Replace 10000 with your desired range for X coordinates
double y = random.Next(-1000, 0); // Replace 10000 with your desired range for Y coordinates
double z = 0; // If you need random Z values, generate them here
MapPoint point = new MapPoint(x, y, z, SpatialReferences.Wgs84);
var textSymbol = new TextSymbol
{
Text = $"{x},{y}",
Color = System.Drawing.Color.Black,
HaloColor = System.Drawing.Color.White,
HaloWidth = 2,
Size = 4,
VerticalAlignment = Esri.ArcGISRuntime.Symbology.VerticalAlignment.Middle,
HorizontalAlignment = Esri.ArcGISRuntime.Symbology.HorizontalAlignment.Center
};
var compositeSymbol = new CompositeSymbol
{
Symbols = { theSimpleMarkerSymbol, textSymbol }
};
mapPoints.Add(new Graphic(point, compositeSymbol));
mapPoints1.Add(new Graphic(point, compositeSymbol));
}
}
I don't see points add all:
When I changed to WebMercator:
MapPoint point = new MapPoint(x, y, z, SpatialReferences.WebMercator);
I see points:
But clustering is still not working:
> So, when i added spatial reference WGS84 (on line 10) I don't see points add all:
Yes your spatial reference you use MUST match the spatial reference of your X and Y, whatever that is. Looks like you're just doing random numbers between 0 and 2000, but I wouldn't know what kind of units that is.
Yes, i am doing random points, but as you can on my screenshot
They are placed.
I can try to put some specific points, but issue still will be reproducible.
Clustering will not working.
Can you provide any information how to make it work with image(raster) layer and clustering of points on it?
Could you zip up a running project and attach here, so we can try and reproduce your issue? It's a little hard to gauge from the small screenshot what the expectation and behavior is.