public async Task<FeatureCollection> CreateNewFeatureCollection(NetTopologySuite.Features.FeatureCollection inputFeatureCollection, Color symbolColor,
bool schematic = false, HashSet<string> puicFilter = null, string filterName = "", GeometricEffect lineEffect = null)
{
FeatureCollection NewFeatureCollection = null;
List<Field> trackAssetFields = new List<Field>();
Field puicField = new Field(FieldType.Guid, "Puic", "Puic Value", 50);
Field nameField = new Field(FieldType.Text, "Name", "Name Value", 50);
Field typeField = new Field(FieldType.Text, "Type", "Type Value", 50);
Field situationField = new Field(FieldType.Text, "Situation", "Situation Value", 50);
Field sideField = new Field(FieldType.Text, "Side", "Side Value", 50);
Field heightField = new Field(FieldType.Float32, "HeightAverage", "HeightAverage Value", 50);
Field rotationField = new Field(FieldType.Float32, "Rotation", "Rotation Value", 0);
Field kilometerRibbonField = new Field(FieldType.Float32, "KMRibbon", "KMRibbon Value", 50);
Field labelPositionField = new Field(FieldType.Float32, "LabelPosition", "LabelPosition Value", 0);
trackAssetFields.Add(puicField);
trackAssetFields.Add(nameField);
trackAssetFields.Add(typeField);
trackAssetFields.Add(sideField);
trackAssetFields.Add(rotationField);
trackAssetFields.Add(kilometerRibbonField);
trackAssetFields.Add(labelPositionField);
trackAssetFields.Add(situationField);
List<Field> lineFields = new List<Field>
{
puicField,
nameField
};
SpatialReference spatialReference = schematic ? new SpatialReference(4839) : new SpatialReference(28992);
Dictionary<string, FeatureCollectionTable> listOfFeatureCollectionTables = new Dictionary<string, FeatureCollectionTable>();
NetTopologySuite.Features.FeatureCollection featureCollection = new NetTopologySuite.Features.FeatureCollection();
inputFeatureCollection.ToList().ForEach(x => featureCollection.Add(x));
//filter feature collection
if (puicFilter != null)
{
featureCollection.Where(x => !puicFilter.Contains(x.Attributes["puic"].ToString())).ToList().ForEach(x => featureCollection.Remove(x));
}
(string, string)[] listOfArrays = featureCollection
.Where(x => x.Attributes.Count > 2)
.GroupBy(x => x.Attributes["arrayName"])
.Select(x => (x.First().Geometry.GeometryType, x.First().Attributes["arrayName"].ToString()))
.ToArray();
FeatureCollectionTable heightLinesTable = null;
FeatureCollectionTable insertionPointTable = new FeatureCollectionTable(trackAssetFields, GeometryType.Point, spatialReference)
{
DisplayName = "insertion points",
Renderer = new SimpleRenderer(new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.X, Color.Purple, 5))
};
IConvenientObjectDesignService convenientObjectDesignService = NetworkAgentFunctionLib.FunctionsKernel.Get<IConvenientObjectDesignService>();
foreach ((string, string) arrayNameGeometryType in listOfArrays)
{
if (arrayNameGeometryType.Item1 == nameof(NetTopologySuite.Geometries.Point))
{
FeatureCollectionTable pointTrackAssetsTable = new FeatureCollectionTable(trackAssetFields, GeometryType.Point, spatialReference)
{
DisplayName = filterName + arrayNameGeometryType.Item2,
Renderer = CreateUniqueValueRenderer(arrayNameGeometryType.Item2, symbolColor, lineEffect)
};
pointTrackAssetsTable.Renderer.RotationExpression = "[Rotation]";
listOfFeatureCollectionTables.Add(arrayNameGeometryType.Item2, pointTrackAssetsTable);
}
else if (arrayNameGeometryType.Item1 == nameof(NetTopologySuite.Geometries.LineString) ||
arrayNameGeometryType.Item1 == nameof(NetTopologySuite.Geometries.MultiLineString))
{
FeatureCollectionTable lineTrackAssetsTable = new FeatureCollectionTable(trackAssetFields, GeometryType.Polyline, spatialReference)
{
DisplayName = filterName + arrayNameGeometryType.Item2
};
switch (arrayNameGeometryType.Item2)
{
case nameof(RHDHVRailAPI.IMSpoorCore.RailConnection):
if (!schematic)
{
trackAssetFields.Add(heightField);
heightLinesTable = CreateHeightMapTable(filterName, trackAssetFields, spatialReference);
lineTrackAssetsTable.Renderer = CreateRenderer(GeometryType.Polyline, Color.DimGray, SimpleLineSymbolStyle.LongDash);
listOfFeatureCollectionTables.Add(arrayNameGeometryType.Item2, lineTrackAssetsTable);
}
else
{
lineTrackAssetsTable.Renderer = CreateRenderer(GeometryType.Polyline, Color.ForestGreen);
listOfFeatureCollectionTables.Add(arrayNameGeometryType.Item2, lineTrackAssetsTable);
}
break;
case nameof(RHDHVRailAPI.IMSpoorCore.AxleCounterSection):
case nameof(RHDHVRailAPI.IMSpoorCore.TrackCircuit):
lineTrackAssetsTable.Renderer = CreateRenderer(GeometryType.Polyline, Color.MediumPurple, SimpleLineSymbolStyle.Dot);
listOfFeatureCollectionTables.Add(arrayNameGeometryType.Item2, lineTrackAssetsTable);
break;
default:
lineTrackAssetsTable.Renderer = CreateRenderer(GeometryType.Polyline, Color.Black, SimpleLineSymbolStyle.Solid);
listOfFeatureCollectionTables.Add(arrayNameGeometryType.Item2, lineTrackAssetsTable);
break;
}
}
}
foreach (NetTopologySuite.Features.IFeature feature in featureCollection)
{
try
{
if (feature.Geometry is NetTopologySuite.Geometries.Point)
{
if (feature.Geometry.Coordinates.FirstOrDefault() == null) { continue; }
// Create a new point feature, provide geometry and attribute values
Esri.ArcGISRuntime.Data.Feature pointFeature = listOfFeatureCollectionTables[feature.Attributes["arrayName"].ToString()].CreateFeature();
NetTopologySuite.Geometries.Point currentPoint = feature.Geometry as NetTopologySuite.Geometries.Point;
pointFeature.SetAttributeValue(puicField, Guid.Parse(feature.Attributes["puic"].ToString()));
pointFeature.SetAttributeValue(nameField, feature.Attributes["name"]);
pointFeature.SetAttributeValue(typeField, feature.Attributes["type"]);
pointFeature.SetAttributeValue(situationField, "design");
if (feature.Attributes.GetNames().Contains("side"))
{
pointFeature.SetAttributeValue(typeField, feature.Attributes["type"].ToString());
}
if (feature.Attributes.GetNames().Contains("LabelPosition") && feature.Attributes.GetNames().Contains("KMRibbonInfo"))
{
pointFeature.SetAttributeValue(labelPositionField, float.Parse(feature.Attributes["LabelPosition"].ToString()));
pointFeature.SetAttributeValue(kilometerRibbonField, float.Parse(feature.Attributes["KMRibbonInfo"].ToString()));
}
pointFeature.SetAttributeValue(rotationField, float.Parse(feature.Attributes["rotation"] == null ? "0" : feature.Attributes["rotation"].ToString()));
MapPoint point1 = new MapPoint(currentPoint.Coordinates[0].X, currentPoint.Coordinates[0].Y, spatialReference);
pointFeature.Geometry = point1;
Esri.ArcGISRuntime.Data.Feature insertionPointFeature = insertionPointTable.CreateFeature();
insertionPointFeature.Geometry = point1;
insertionPointFeature.SetAttributeValue(typeField, "InsertionPoint");
try
{
await listOfFeatureCollectionTables[feature.Attributes["arrayName"].ToString()].AddFeatureAsync(pointFeature);
await insertionPointTable.AddFeatureAsync(insertionPointFeature);
}
catch (Exception e2)
{
_ = MessageBox.Show(e2.ToString(), "Error");
}
}
else if (feature.Geometry is NetTopologySuite.Geometries.LineString && feature.Geometry.Coordinates.Length > 1)
{
// Create a new line feature, provide geometry and attribute values
Feature lineFeature = listOfFeatureCollectionTables[feature.Attributes["arrayName"].ToString()].CreateFeature();
lineFeature.SetAttributeValue(puicField, Guid.Parse(feature.Attributes["puic"].ToString()));
lineFeature.SetAttributeValue(nameField, feature.Attributes["name"]);
lineFeature.SetAttributeValue(typeField, feature.Attributes["type"]);
List<MapPoint> mapPoints = new List<MapPoint>();
NetTopologySuite.Geometries.LineString currentLineString = feature.Geometry as NetTopologySuite.Geometries.LineString;
mapPoints.AddRange(currentLineString.Coordinates.Select(cdns => new MapPoint(cdns.X, cdns.Y)));
if (feature.Attributes["arrayName"].ToString() == nameof(RHDHVRailAPI.IMSpoorCore.RailConnection) && !schematic && heightLinesTable != null)
{
for (int i = 0; i < currentLineString.Coordinates.Length - 1; i++)
{
Feature subLineFeature = heightLinesTable.CreateFeature();
NetTopologySuite.Geometries.Coordinate cdns = currentLineString.Coordinates[i];
NetTopologySuite.Geometries.Coordinate nextCdn = currentLineString.Coordinates[i + 1];
Polyline subLine = new Polyline(new List<MapPoint>() { new MapPoint(cdns.X, cdns.Y), new MapPoint(nextCdn.X, nextCdn.Y) });
subLineFeature.SetAttributeValue(heightField, float.Parse((Math.Abs(cdns.Z - nextCdn.Z) + cdns.Z).ToString()));
subLineFeature.Geometry = subLine;
await heightLinesTable.AddFeatureAsync(subLineFeature);
}
}
Polyline line = new Polyline(mapPoints);
lineFeature.Geometry = line;
await listOfFeatureCollectionTables[feature.Attributes["arrayName"].ToString()].AddFeatureAsync(lineFeature);
}
else if (feature.Geometry is NetTopologySuite.Geometries.MultiLineString multiLineString && feature.Geometry.Coordinates.Length > 1)
{
Feature lineFeature = listOfFeatureCollectionTables[feature.Attributes["arrayName"].ToString()].CreateFeature();
lineFeature.SetAttributeValue(puicField, Guid.Parse(feature.Attributes["puic"].ToString()));
lineFeature.SetAttributeValue(nameField, feature.Attributes["name"]);
lineFeature.SetAttributeValue(typeField, feature.Attributes["type"]);
List<Segment[]> allSegments = new List<Segment[]>();
foreach (NetTopologySuite.Geometries.Geometry lineString in multiLineString.Geometries)
{
List<Segment> segments = new List<Segment>();
for (int i = 0; i < lineString.Coordinates.Length - 1; i++)
{
var startCoordinate = lineString.Coordinates[i];
var endCoordinate = lineString.Coordinates[i + 1];
segments.Add(
new Esri.ArcGISRuntime.Geometry.LineSegment
(
new MapPoint(startCoordinate.X, startCoordinate.Y),
new MapPoint(endCoordinate.X, endCoordinate.Y), spatialReference
));
}
allSegments.Add(segments.ToArray());
}
Polyline line = new Polyline(allSegments);
lineFeature.Geometry = line;
await listOfFeatureCollectionTables[feature.Attributes["arrayName"].ToString()].AddFeatureAsync(lineFeature);
}
}
catch (Exception e)
{
//TODO: handle exception
//this means something has gone wrong while loading, should be added to a load error list
}
}
try
{
// Create a feature collection and add the feature collection tables
NewFeatureCollection = new FeatureCollection();
if (heightLinesTable != null) { NewFeatureCollection.Tables.Add(heightLinesTable); }
NewFeatureCollection.Tables.Add(insertionPointTable);
foreach (FeatureCollectionTable pointTable in listOfFeatureCollectionTables.Values)
{
NewFeatureCollection.Tables.Add(pointTable);
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "Error");
}
return NewFeatureCollection;
}
private static FeatureCollectionTable CreateHeightMapTable(string filterName, List<Field> trackAssetFields, SpatialReference spatialReference)
{
FeatureCollectionTable heightLinesTable = new FeatureCollectionTable(trackAssetFields, GeometryType.Polyline, spatialReference)
{
DisplayName = filterName + "HeightMap",
Renderer = new ClassBreaksRenderer("HeightAverage", new List<ClassBreak>()
{
new ClassBreak("0 to 1", "-4 - -3", -3,-2, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,255,0), 3)),
new ClassBreak("0 to 1", "-3 - -2", -3,-2, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,250,0), 3)),
new ClassBreak("0 to 1", "-2 - -1", -2,-1, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,245,0), 3)),
new ClassBreak("0 to 1", "-1 - -0", -1, 0, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,244,0), 3)),
new ClassBreak("0 to 1", "0 - 1", 0, 1, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,242,0), 3)),
new ClassBreak("0 to 1", "1 - 2", 1, 2, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,240,0), 3)),
new ClassBreak("0 to 1", "2 - 3", 2, 3, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,220,0), 3)),
new ClassBreak("0 to 1", "3 - 4", 3, 4, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,200,0), 3)),
new ClassBreak("0 to 1", "4 - 5", 4, 5, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,180,0), 3)),
new ClassBreak("0 to 1", "5 - 6", 5, 6, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,160,0), 3)),
new ClassBreak("0 to 1", "6 - 7", 6, 7, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,140,0), 3)),
new ClassBreak("0 to 1", "7 - 8", 7, 8, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,120,0), 3)),
new ClassBreak("0 to 1", "8 - 9", 8, 9, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,100,0), 3)),
new ClassBreak("0 to 1", "9 - 10,", 9, 10, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,80,0), 3)),
new ClassBreak("0 to 1", "10 - 11", 10, 11, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,60,0), 3)),
new ClassBreak("0 to 1", "11 - 12", 11, 12, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,40,0), 3)),
new ClassBreak("0 to 1", "12 - 13", 12, 13, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,35,0), 3)),
new ClassBreak("0 to 1", "13 - 14", 13, 14, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,30,0), 3)),
new ClassBreak("0 to 1", "14 - 15", 13, 14, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,20,0), 3)),
new ClassBreak("0 to 1", "15 - 16", 13, 14, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.FromArgb(255,255,10,0), 3)),
}
)
};
return heightLinesTable;
}
/// <summary>
/// this method creates a renderer that contains symbols for each unique object type
/// symbols have been extracted from autocad plugin and are contained in this project in a json file
/// </summary>
/// <returns></returns>
public UniqueValueRenderer CreateUniqueValueRenderer(string typeName, Color symbolColor, GeometricEffect lineEffect)
{
string symbolsJSON = System.IO.File.ReadAllText(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "/resources/symbols_autocad_updated.json");
GeoJSON.Net.Feature.FeatureCollection symbolCollection = JsonConvert.DeserializeObject<GeoJSON.Net.Feature.FeatureCollection>(symbolsJSON);
IMSpoorObjectCreationFunctions objectCreationFunctions = CoreFunctionLib.FunctionsKernel.Get<IMSpoorObjectCreationFunctions>();
UniqueValueRenderer trackAssetRenderer = new UniqueValueRenderer();
trackAssetRenderer.FieldNames.Add("type");
trackAssetRenderer.FieldNames.Add("situation");
object MagicallyCreateOtherInstance(string className)
{
try
{
var assembly = Assembly.GetAssembly(typeof(VirtualDangerPoint));
var assemblyNA = Assembly.GetAssembly(typeof(VirtualTrackAsset));
List<Type> typesList = new List<Type>();
foreach (Type t in assembly.GetTypes())
{
typesList.Add(t);
}
foreach (Type t in assemblyNA.GetTypes())
{
typesList.Add(t);
}
var types = typesList.First(t => t.Name == className);
return Activator.CreateInstance(types);
}
catch
{
return null;
}
}
object imspoorObjectTypeInstance = ImspoorType.GetByName(typeName) != null ?
objectCreationFunctions.CreateInstance(typeName) : MagicallyCreateOtherInstance(typeName);
string type = "";
PropertyInfo typeProperty = imspoorObjectTypeInstance.GetType().GetProperty
($"{Char.ToLowerInvariant(imspoorObjectTypeInstance.GetType().Name[0]) + imspoorObjectTypeInstance.GetType().Name.Substring(1)}Type");
Type enumType = null;
if (typeProperty != null)
{
enumType = typeProperty.PropertyType;
}
else
{
type = imspoorObjectTypeInstance.GetType().Name;
}
for (int i = 0; i < symbolCollection.Features.Count; i++)
{
GeoJSON.Net.Feature.Feature feature = symbolCollection.Features[i];
if (type != feature.Properties["assetName"].ToString() && !(enumType != null && Enum.IsDefined(enumType, feature.Properties["assetName"].ToString())))
{
continue;
}
List<VectorMarkerSymbolElement> vectorMarkerSymbolElements = new List<VectorMarkerSymbolElement>();
SolidStrokeSymbolLayer lineSymbol = lineEffect is null ? new SolidStrokeSymbolLayer(1, symbolColor) : new SolidStrokeSymbolLayer(1, symbolColor, new List<GeometricEffect>() { lineEffect });
List<SymbolLayer> symbolLayers = new List<SymbolLayer>
{
lineSymbol
};
MultilayerPolylineSymbol multilayerPolylineSymbol = new MultilayerPolylineSymbol(symbolLayers);
double symbolSizeLength = 15;
if (feature.Geometry is GeoJSON.Net.Geometry.MultiLineString)
{
vectorMarkerSymbolElements = GetSymbolGeometry(feature, out NetTopologySuite.Geometries.MultiLineString multiLineString, multilayerPolylineSymbol, symbolColor, lineEffect);
if (multiLineString.Envelope.Area > 0)
{
List<double> xS = new List<double>();
List<double> yS = new List<double>();
foreach (NetTopologySuite.Geometries.Coordinate cdn in multiLineString.Coordinates)
{
xS.Add(cdn.X);
yS.Add(cdn.Y);
}
double maxX = xS.Max();
double minX = xS.Min();
double maxY = yS.Max();
double minY = yS.Min();
double pythLength = Math.Sqrt(Math.Pow((maxX - minX), 2) + Math.Pow((maxY - minY), 2));
symbolSizeLength = pythLength;
}
}
List<VectorMarkerSymbolLayer> vectorMarkerSymbolLayers = new List<VectorMarkerSymbolLayer>();
VectorMarkerSymbolLayer symLyr = new VectorMarkerSymbolLayer(vectorMarkerSymbolElements);
double minXel = 0;
double maxXel = 0;
foreach (VectorMarkerSymbolElement element in vectorMarkerSymbolElements)
{
maxXel = maxXel > element.Geometry.Extent.XMax ? maxXel : element.Geometry.Extent.XMax;
minXel = minXel < element.Geometry.Extent.XMin ? minXel : element.Geometry.Extent.XMin;
}
symLyr.Anchor = new SymbolAnchor(-0.5, 0, SymbolAnchorPlacementMode.Relative);
MultilayerPointSymbol sym;
if (feature.Properties["assetName"].ToString() == "Unknown")
{
symLyr.Size = symbolSizeLength * 0.07;
}
else if (Enum.IsDefined(typeof(RHDHVRailAPI.IMSpoorCore.tSignalEnum), feature.Properties["assetName"].ToString()))
{
symLyr.Size = symbolSizeLength * 1.5;
}
else if (feature.Properties["assetName"].ToString().Contains("Crossing"))
{
symLyr.Size = symbolSizeLength * 1.5;
symLyr.Anchor = new SymbolAnchor(0, 0, SymbolAnchorPlacementMode.Relative);
}
else if (feature.Properties["assetName"].ToString() == "SingleSwitch")
{
symLyr.Size = symbolSizeLength * 1;
symLyr.Anchor = new SymbolAnchor(0, -0.5, SymbolAnchorPlacementMode.Relative);
List<VectorMarkerSymbolElement> singleSwitchMirrored = GetSymbolGeometry(feature, out NetTopologySuite.Geometries.MultiLineString multiLineString, multilayerPolylineSymbol, symbolColor, lineEffect, -1);
List<VectorMarkerSymbolLayer> vectorMarkerSymbolLayersSwitch = new List<VectorMarkerSymbolLayer>();
VectorMarkerSymbolLayer symLyrSwitch = new VectorMarkerSymbolLayer(singleSwitchMirrored)
{
Size = symbolSizeLength * 1,
Anchor = new SymbolAnchor(0, 0.5, SymbolAnchorPlacementMode.Relative)
};
vectorMarkerSymbolLayersSwitch.Add(symLyrSwitch);
sym = new MultilayerPointSymbol(vectorMarkerSymbolLayersSwitch)
{
AngleAlignment = SymbolAngleAlignment.Map
};
trackAssetRenderer.UniqueValues.Add(new UniqueValue(feature.Properties["assetName"].ToString(), feature.Properties["assetName"].ToString(), sym, new string[] { feature.Properties["assetName"].ToString() + "R", "design" }));
}
else if (feature.Properties["assetName"].ToString() == "StopMarkerBoard")
{
symLyr.Size = symbolSizeLength * 2;
symLyr.Anchor = new SymbolAnchor(-0.5, 0, SymbolAnchorPlacementMode.Relative);
List<VectorMarkerSymbolElement> stopMarkerBoardMirrored = GetSymbolGeometry(feature, out NetTopologySuite.Geometries.MultiLineString multiLineString, multilayerPolylineSymbol, symbolColor, lineEffect, -1);
List<VectorMarkerSymbolLayer> vectorMarkerSymbolLayersSwitch = new List<VectorMarkerSymbolLayer>();
VectorMarkerSymbolLayer symlyrSMB = new VectorMarkerSymbolLayer(stopMarkerBoardMirrored)
{
Size = symbolSizeLength * 2,
Anchor = new SymbolAnchor(-0.5, 0, SymbolAnchorPlacementMode.Relative)
};
vectorMarkerSymbolLayersSwitch.Add(symlyrSMB);
sym = new MultilayerPointSymbol(vectorMarkerSymbolLayersSwitch)
{
AngleAlignment = SymbolAngleAlignment.Map
};
trackAssetRenderer.UniqueValues.Add(new UniqueValue(feature.Properties["assetName"].ToString(), feature.Properties["assetName"].ToString(), sym, new string[] { feature.Properties["assetName"].ToString() + "R", "design" }));
}
else if (ImspoorType.GetByName("tDepartureSignalEnum") != null && Enum.IsDefined(objectCreationFunctions.CreateInstance("tDepartureSignalEnum").GetType(), feature.Properties["assetName"].ToString()))
{
vectorMarkerSymbolElements = GetSymbolGeometry(feature, out NetTopologySuite.Geometries.MultiLineString multiLineString, multilayerPolylineSymbol, symbolColor, lineEffect, 1);
symLyr = new VectorMarkerSymbolLayer(vectorMarkerSymbolElements)
{
Size = symbolSizeLength * 3,
Anchor = new SymbolAnchor(0, -0.26, SymbolAnchorPlacementMode.Relative),
Heading = 180
};
}
else if (Enum.IsDefined(typeof(RHDHVRailAPI.IMSpoorCore.tSpeedSignEnum), feature.Properties["assetName"].ToString()))
{
symLyr.Size = symbolSizeLength * 2;
}
else if (Enum.IsDefined(typeof(RHDHVRailAPI.IMSpoorCore.tSignEnum), feature.Properties["assetName"].ToString()))
{
symLyr.Size = symbolSizeLength * 2;
}
else if (feature.Properties["assetName"].ToString() == "AxleCounterDetectionPoint")
{
symLyr.Size = symbolSizeLength * 4;
symLyr.Anchor = new SymbolAnchor(0, -0.5, SymbolAnchorPlacementMode.Relative);
}
else if (feature.Properties["assetName"].ToString() == "InsulatedJoint")
{
symLyr.Size = symbolSizeLength * 2;
symLyr.Anchor = new SymbolAnchor(0, 0, SymbolAnchorPlacementMode.Relative);
}
else if (feature.Properties["assetName"].ToString() == "ATBVVBeacon")
{
symLyr.Size = symbolSizeLength * 4;
symLyr.Anchor = new SymbolAnchor(0, 0.5, SymbolAnchorPlacementMode.Relative);
}
else if (feature.Properties["assetName"].ToString() == "PPCTrack")
{
symLyr.Anchor = new SymbolAnchor(0, 0, SymbolAnchorPlacementMode.Relative);
}
else if (feature.Properties["assetName"].ToString() == "Pedal")
{
symLyr.Size = symbolSizeLength * 2;
}
else if (feature.Properties["assetName"].ToString() == "None")
{
symLyr.Anchor = new SymbolAnchor(0, 0, SymbolAnchorPlacementMode.Relative);
symLyr.Size = symbolSizeLength * 1;
}
vectorMarkerSymbolLayers.Add(symLyr);
sym = new MultilayerPointSymbol(vectorMarkerSymbolLayers)
{
AngleAlignment = SymbolAngleAlignment.Map,
};
trackAssetRenderer.UniqueValues.Add(new UniqueValue(feature.Properties["assetName"].ToString(),
feature.Properties["assetName"].ToString(), sym, new string[] { feature.Properties["assetName"].ToString(), "design" }));
MultilayerPointSymbol redSym = new MultilayerPointSymbol(vectorMarkerSymbolLayers)
{
Color = Color.Red
};
}
if (imspoorObjectTypeInstance is RHDHVRailAPI.FlankProtection.Objects.VirtualDangerPoint)
{
trackAssetRenderer.UniqueValues.Add(new UniqueValue(type, type, testSymbol(), new string[] { type, "design" }));
}
else if (imspoorObjectTypeInstance is RHDHVRailAPI.NetworkAgent.ConvenientObjects.JunctionMathematicalPoint)
{
trackAssetRenderer.UniqueValues.Add(new UniqueValue(type, type, new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.Black, 5), new string[] { type, "design" }));
}
else if (imspoorObjectTypeInstance is RHDHVRailAPI.NetworkAgent.ConvenientObjects.PlatformWallEndMarker)
{
trackAssetRenderer.UniqueValues.Add(new UniqueValue(type, type, new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Cross, Color.Yellow, 5), new string[] { type, "design" }));
}
return trackAssetRenderer;
}
private List<VectorMarkerSymbolElement> GetSymbolGeometry(GeoJSON.Net.Feature.Feature feature, out
NetTopologySuite.Geometries.MultiLineString outputmultiLineString, MultilayerPolylineSymbol multilayerPolylineSymbol, Color symbolColor, GeometricEffect lineEffect, int mirrorMultiplier = 1)
{
List<VectorMarkerSymbolElement> vectorMarkerSymbolElements = new List<VectorMarkerSymbolElement>();
GeoJSON.Net.Geometry.MultiLineString multiLineString = feature.Geometry as GeoJSON.Net.Geometry.MultiLineString;
List<NetTopologySuite.Geometries.LineString> linestringsNet = new List<NetTopologySuite.Geometries.LineString>();
foreach (GeoJSON.Net.Geometry.LineString lineString in multiLineString.Coordinates)
{
List<MapPoint> mapPoints = new List<MapPoint>();
List<NetTopologySuite.Geometries.Coordinate> coordinates = new List<NetTopologySuite.Geometries.Coordinate>();
foreach (GeoJSON.Net.Geometry.IPosition coordinate in lineString.Coordinates)
{
mapPoints.Add(new MapPoint(coordinate.Latitude, coordinate.Longitude * mirrorMultiplier));
coordinates.Add(new NetTopologySuite.Geometries.Coordinate(coordinate.Latitude, coordinate.Longitude * mirrorMultiplier));
}
NetTopologySuite.Geometries.LineString netSuiteLineString = new NetTopologySuite.Geometries.LineString(coordinates.ToArray());
linestringsNet.Add(netSuiteLineString);
VectorMarkerSymbolElement symLyrEl = new VectorMarkerSymbolElement(new Polyline(mapPoints), multilayerPolylineSymbol);
vectorMarkerSymbolElements.Add(symLyrEl);
}
if (feature.Properties.ContainsKey("SimpleMarkerSymbol"))
{
string symbolInfo = feature.Properties["SimpleMarkerSymbol"].ToString();
GeoJSON.Net.Geometry.Point[] symbolGeometries = JsonConvert.DeserializeObject<GeoJSON.Net.Geometry.Point[]>(symbolInfo);
SimpleMarkerSymbol pointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.Transparent, symbolGeometries[0].Coordinates.Latitude * 1.3)
{
Color = Color.Transparent,
Outline = new SimpleLineSymbol(lineEffect is DashGeometricEffect ? SimpleLineSymbolStyle.Dash : SimpleLineSymbolStyle.Solid, symbolColor, 1)
};
pointSymbol.Style = SimpleMarkerSymbolStyle.Circle;
MultilayerPointSymbol multilayerPointSymbol = pointSymbol.ToMultilayerSymbol();
//multilayerPointSymbol.ReferenceProperties = new SymbolReferenceProperties(20000, 0);
VectorMarkerSymbolElement vectorMarkerSymbolElement = new VectorMarkerSymbolElement(new MapPoint(symbolGeometries[1].Coordinates.Latitude,
symbolGeometries[1].Coordinates.Longitude * mirrorMultiplier), multilayerPointSymbol);
vectorMarkerSymbolElements.Add(vectorMarkerSymbolElement);
}
outputmultiLineString = new NetTopologySuite.Geometries.MultiLineString(linestringsNet.ToArray());
return vectorMarkerSymbolElements;
}
MultilayerPointSymbol testSymbol()
{
SolidStrokeSymbolLayer lineSymbol = new SolidStrokeSymbolLayer(1, Color.Black);
List<SymbolLayer> symbolLayers = new List<SymbolLayer>
{
lineSymbol
};
MultilayerPolylineSymbol multilayerPolylineSymbol = new MultilayerPolylineSymbol(symbolLayers);
List<MapPoint> mapPoints = new List<MapPoint>();
Coordinate[] coordinatesArray = new Coordinate[] { new Coordinate(0, 0), new Coordinate(5, 0), new Coordinate(5, 2), new Coordinate(5, -2) };
SymbolReferenceProperties symbolReferenceProperties = new SymbolReferenceProperties(10000.0, 1.0);
foreach (Coordinate coordinate in coordinatesArray)
{
mapPoints.Add(new MapPoint(coordinate.X, coordinate.Y));
}
multilayerPolylineSymbol.ReferenceProperties = symbolReferenceProperties;
VectorMarkerSymbolElement symLyrEl = new VectorMarkerSymbolElement(new Polyline(mapPoints), multilayerPolylineSymbol);
List<VectorMarkerSymbolElement> vectorMarkerSymbolElements = new List<VectorMarkerSymbolElement>();
//add custom element to vectormarker symbol
vectorMarkerSymbolElements.Add(symLyrEl);
SimpleMarkerSymbol pointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.Transparent, 5)
{
Color = Color.Transparent,
Outline = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.Black, 1),
};
pointSymbol.Style = SimpleMarkerSymbolStyle.Circle;
MultilayerPointSymbol multilayerPointSymbol = pointSymbol.ToMultilayerSymbol();
multilayerPointSymbol.ReferenceProperties = symbolReferenceProperties;
VectorMarkerSymbolElement vectorMarkerSymbolElement = new VectorMarkerSymbolElement(new MapPoint(0, 10), multilayerPointSymbol);
vectorMarkerSymbolElement.Symbol.ReferenceProperties = symbolReferenceProperties;
//add circle symbol to vectormarker symbol
vectorMarkerSymbolElements.Add(vectorMarkerSymbolElement);
VectorMarkerSymbolLayer symLyr = new VectorMarkerSymbolLayer(vectorMarkerSymbolElements);
List<VectorMarkerSymbolLayer> vectorMarkerSymbolLayers = new List<VectorMarkerSymbolLayer>();
vectorMarkerSymbolLayers.Add(symLyr);
MultilayerPointSymbol sym = new MultilayerPointSymbol(vectorMarkerSymbolLayers)
{
AngleAlignment = SymbolAngleAlignment.Map,
ReferenceProperties = symbolReferenceProperties
};
return sym;
}
internal Renderer CreateRenderer(GeometryType rendererType, Color color, SimpleLineSymbolStyle lineSymbolStyle = SimpleLineSymbolStyle.Solid)
{
// Return a simple renderer to match the geometry type provided
Esri.ArcGISRuntime.Symbology.Symbol sym = null;
switch (rendererType)
{
case GeometryType.Point:
case GeometryType.Multipoint:
SolidStrokeSymbolLayer lineSymbol = new SolidStrokeSymbolLayer(2, Color.Red);
List<SymbolLayer> symbolLayers = new List<SymbolLayer>
{
lineSymbol
};
MultilayerPolylineSymbol multilayerPolylineSymbol = new MultilayerPolylineSymbol(symbolLayers);
List<VectorMarkerSymbolElement> vectorMarkerSymbolElements = new List<VectorMarkerSymbolElement>();
List<MapPoint> mapPoints = new List<MapPoint>
{
new MapPoint(0, 0),
new MapPoint(0, 5)
};
VectorMarkerSymbolElement symLyrEl = new VectorMarkerSymbolElement(new Polyline(mapPoints), multilayerPolylineSymbol);
vectorMarkerSymbolElements.Add(symLyrEl);
List<VectorMarkerSymbolLayer> vectorMarkerSymbolLayers = new List<VectorMarkerSymbolLayer>();
VectorMarkerSymbolLayer symLyr = new VectorMarkerSymbolLayer(vectorMarkerSymbolElements);
vectorMarkerSymbolLayers.Add(symLyr);
sym = new MultilayerPointSymbol(vectorMarkerSymbolLayers);
break;
case GeometryType.Polyline:
// Create a line symbol
sym = new SimpleLineSymbol(lineSymbolStyle, color, 2);
break;
case GeometryType.Polygon:
// Create a fill symbol
SimpleLineSymbol lineSym = new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.DarkBlue, 2);
sym = new SimpleFillSymbol(SimpleFillSymbolStyle.DiagonalCross, Color.Cyan, lineSym);
break;
default:
break;
}
// Return a new renderer that uses the symbol created above
return new SimpleRenderer(sym);
}
Hi Priyanka,
maybe this helps. I've attached the complete code. You can see how I'm using unique value renderers to specify which symbols to load for specific features.
Also the method "testSymbol" is included, that is the symbol we've been talking about as an example. You can see I set the reference properties at all points. Also when I don't set any referenceproperties, it does not work.
when the featurecollection is completed, and the featurecollectionlayer is loaded, the following code is executed.
private async void FeatureCollectionLayer_Loaded(object sender, EventArgs e)
{
GeographicMapViewModel geographicViewModel = GeographicMapView.DataContext as GeographicMapViewModel;
MapservicesViewModel mapservicesViewModel = geographicViewModel.MapservicesControl.DataContext as MapservicesViewModel;
GeographicMapView.BackgroundGrid.IsVisible = false;
geographicViewModel.FeatureCollectionLayer.Layers[0].ScaleSymbols = false;
for (int i = 1; i < geographicViewModel.FeatureCollectionLayer.Layers.Count; i++)
{
geographicViewModel.FeatureCollectionLayer.Layers[i].ScaleSymbols = true;
}
GeographicMapView.Map.ReferenceScale = 445;
await GeographicMapView.Map.LoadAsync();
GeographicMapView.Map.OperationalLayers.AddRange(mapservicesViewModel.ListMapservicesList);
GeographicMapView.Map.OperationalLayers.Add(geographicViewModel.FeatureCollectionLayer);
MeasureToolbar.SelectedLinearUnit = MeasureToolbar.LinearUnits[4];
_ = await GeographicMapView.SetViewpointCenterAsync(geographicViewModel.FeatureCollectionLayer.FullExtent.GetCenter(), scale: 10000);
_ = await GeographicMapView.SetViewpointScaleAsync(445);
LoadWindow.Loading = false;
LoadWindow.Visibility = Visibility.Collapsed;
}