private void DrawLegend() { if (_legendFont == null || _legendFont.IsDisposed) { _legendFont = Surface.Fonts.GetTextFormat(MM_Repository.OverallDisplay.NetworkMapFont); } Vector2 start = new Vector2(30, 30 + MM_Repository.KVLevels.Count * 20 + 10); Vector2 end = start + new Vector2(235, 125); Surface.RenderTarget2D.FillRectangle(new RawRectangleF(start.X - 10, start.Y - 10, end.X + 20, end.Y + 10), Surface.Brushes.GetBrush(new Color4(0, 0, 0, 0.5f))); var position = start + new Vector2(20, 5); var offset = new Vector2(50, 0); var textOffset = new Vector2(0, 15); var whiteBrush = Surface.Brushes.GetBrush(Color4.White); foreach (var fuelColor in SubstationLayer.FuelColors) { if (position.X > end.X) { position.X = start.X + 20; position.Y += textOffset.Y * 3; } var brush = Surface.Brushes.GetBrush(fuelColor.Value, 0.6f); if (fuelColor.Key == "LOAD") { Surface.RenderTarget2D.FillRectangle(new RectangleF(position.X - 7.5f, position.Y - 7.5f, 15, 15), brush); } else { Surface.RenderTarget2D.FillEllipse(new Ellipse(position, 10, 10), brush); } using (var layout = new TextLayout(Surface.FactoryDirectWrite, fuelColor.Key, _legendFont, offset.X, 14)) { var textLoc = position + textOffset; Surface.RenderTarget2D.DrawTextAtPoint(layout, whiteBrush, textLoc.X, textLoc.Y, centerX: true, options: DrawTextOptions.Clip); position += offset; } } var onlineBrush = Surface.Brushes.GetBrush(SubstationLayer.FuelColors["WIND"], 0.6f); var tx = Surface.RenderTarget2D.Transform; Surface.RenderTarget2D.Transform = Matrix3x2.Translation(position); if (_slice != null && !_slice.IsDisposed) { Surface.RenderTarget2D.FillGeometry(_slice, onlineBrush); } Surface.RenderTarget2D.Transform = tx; Surface.RenderTarget2D.DrawEllipse(new Ellipse(position, 10, 10), onlineBrush); using (var layout = new TextLayout(Surface.FactoryDirectWrite, "MW & Max", _legendFont, offset.X, 14)) { var textLoc = position + textOffset; Surface.RenderTarget2D.DrawTextAtPoint(layout, whiteBrush, textLoc.X, textLoc.Y, centerX: true, options: DrawTextOptions.Clip); } position += offset; if (position.X > end.X) { position.X = start.X + 20; position.Y += textOffset.Y * 3; } Surface.RenderTarget2D.DrawEllipse(new Ellipse(position, 10, 10), onlineBrush, 2f, _dashStyle); using (var layout = new TextLayout(Surface.FactoryDirectWrite, "Offline", _legendFont, offset.X, 14)) { var textLoc = position + textOffset; Surface.RenderTarget2D.DrawTextAtPoint(layout, whiteBrush, textLoc.X, textLoc.Y, centerX: true, options: DrawTextOptions.Clip); } position += offset; if (position.X > end.X) { position.X = start.X + 20; position.Y += textOffset.Y * 3; } using (var layout = new TextLayout(Surface.FactoryDirectWrite, "Unit", _legendFont, offset.X, 14)) using (var geom = SharpDxExtensions.CreatePathGeometry(Surface.Factory2D, true, true, new Vector2(position.X - 5, position.Y), new Vector2(position.X, position.Y - 5), new Vector2(position.X + 5, position.Y), new Vector2(position.X, position.Y + 5))) { Surface.RenderTarget2D.FillGeometry(geom, whiteBrush); var textLoc = position + textOffset; Surface.RenderTarget2D.DrawTextAtPoint(layout, whiteBrush, textLoc.X, textLoc.Y, centerX: true, options: DrawTextOptions.Clip); } position += offset; if (position.X > end.X) { position.X = start.X + 20; position.Y += textOffset.Y * 3; } Surface.RenderTarget2D.FillRectangle(new RectangleF(position.X - 2, position.Y - 2, 2 * 2f, 2 * 2f), whiteBrush); using (var layout = new TextLayout(Surface.FactoryDirectWrite, "Substation", _legendFont, offset.X, 14)) { var textLoc = position + textOffset; Surface.RenderTarget2D.DrawTextAtPoint(layout, whiteBrush, textLoc.X, textLoc.Y, centerX: true, options: DrawTextOptions.Clip); } }
private void DrawSubstations(RawRectangleF bounds, int zoomLevel, bool showViolation) { foreach (var proxy in _substationProxies.Values) { proxy.Visible = false; if (proxy.BlackStartHidden) { continue; } // check visibility and bounds if (!bounds.Contains(proxy.Coordinates)) { continue; } if (!IsVisible(proxy, zoomLevel)) { continue; } MM_DisplayParameter Disp = proxy.Substation.SubstationDisplay(_violationViewer.ShownViolations, Surface); if (Disp.Blink && !showViolation) { Disp = MM_Repository.SubstationDisplay; } bool showingViolation = Disp != MM_Repository.SubstationDisplay; bool isInternal = proxy.Substation.IsInternal; var DrawColor = Disp.ForeColor; float width = Disp.Width; //If drawing the substation with voltage profile, update the color accordingly if (MM_Repository.SubstationDisplay.ShowSubstationVoltages && (!Disp.Blink || (Disp.Blink && showViolation))) { try { float WorstPu = proxy.Substation.Average_pU; if (float.IsNaN(WorstPu)) { DrawColor = Color.FromArgb(50, 50, 50); } else if ((WorstPu >= 1f + (MM_Repository.OverallDisplay.ContourThreshold / 100f) || WorstPu <= 1f - (MM_Repository.OverallDisplay.ContourThreshold / 100f))) { DrawColor = RelativeColor(WorstPu - 1f); } } catch { /* suppress errors */ } } if (proxy.BlackStartDim) { DrawColor = MM_Repository.OverallDisplay.BlackstartDim(DrawColor); } proxy.Color = DrawColor.ToDxColor4(); var solidColorBrush = Surface.Brushes.GetBrush(proxy.Color); bool drawBubbles = false; proxy.Visible = true; drawBubbles = MM_Repository.SubstationDisplay.GeneratorBubblesMode != MM_Substation_Display.MM_Generator_Bubble_Mode.None; bool fuelBubbleVisible = false; bool loadBubbleVisible = false; // Draw load squares if requested if (proxy.Substation.HasLoads && MM_Repository.SubstationDisplay.ShowLoadBubbles) { DrawLoadBubbles(proxy, zoomLevel); loadBubbleVisible = true; } if (drawBubbles && proxy.Substation.HasUnits) { DrawFuelBubbles(proxy, zoomLevel); fuelBubbleVisible = true; } if (MM_Repository.SubstationDisplay.ShowReserveZones && proxy.Substation.HasUnits) { ShowReserveZonesBubbles(proxy, zoomLevel); } // Draw unit substations if (proxy.Substation.HasUnits && (MM_Repository.SubstationDisplay.ShowSubstations == MM_Substation_Display.SubstationViewEnum.Units || MM_Repository.SubstationDisplay.ShowSubstations == MM_Substation_Display.SubstationViewEnum.All)) { if ((showingViolation || !fuelBubbleVisible)) { // scale down diamonds for substations if we are drawing bubbles float scale = 1.75f; using (var geom = SharpDxExtensions.CreatePathGeometry(Surface.Factory2D, true, true, new Vector2(proxy.Coordinates.X - (width * scale), proxy.Coordinates.Y), new Vector2(proxy.Coordinates.X, proxy.Coordinates.Y - (width * scale)), new Vector2(proxy.Coordinates.X + (width * scale), proxy.Coordinates.Y), new Vector2(proxy.Coordinates.X, proxy.Coordinates.Y + (width * scale)))) { Surface.RenderTarget2D.FillGeometry(geom, solidColorBrush); } } } else if ((showingViolation || !loadBubbleVisible)) { // we don't need to AA squares. this saves performance var aa = Surface.RenderTarget2D.AntialiasMode; Surface.RenderTarget2D.AntialiasMode = AntialiasMode.Aliased; Surface.RenderTarget2D.FillRectangle(new RectangleF(proxy.Coordinates.X - width, proxy.Coordinates.Y - width, width * 2f, width * 2f), solidColorBrush); Surface.RenderTarget2D.AntialiasMode = aa; } bool hasIcon = DrawIcons(proxy, showViolation); if (proxy.Substation.KVLevels != null) { foreach (MM_KVLevel Voltage in proxy.Substation.KVLevels) { if (zoomLevel >= Voltage.StationMW || zoomLevel >= Voltage.StationNames) { DrawText(proxy, zoomLevel, solidColorBrush, hasIcon); } } } } }