private static bool IsLineVisible(RawRectangleF coordinateBounds, LineProxy line, int zoomLevel) { if (line == null || line.Coordinates == null || line.Coordinates.Count < 2) { return(false); } if (line.BaseLine == null) { return(false); } if (!coordinateBounds.Overlaps(line.Bounds)) { return(false); } if (line.BaseLine.KVLevel.VisibilityByZoom > zoomLevel) { return(false); } if (!line.BaseLine.KVLevel.ShowEnergized && (line.BaseLine.LineEnergizationState == line.BaseLine.KVLevel.Energized)) { return(false); } if (!line.BaseLine.KVLevel.ShowUnknown && (line.BaseLine.LineEnergizationState == line.BaseLine.KVLevel.Unknown)) { return(false); } if (!line.BaseLine.KVLevel.ShowDeEnergized && (line.BaseLine.LineEnergizationState == line.BaseLine.KVLevel.DeEnergized)) { return(false); } if (!line.BaseLine.KVLevel.ShowPartiallyEnergized && (line.BaseLine.LineEnergizationState == line.BaseLine.KVLevel.PartiallyEnergized)) { return(false); } if (line.BaseLine.KVLevel.VisibilityThreshold > 0f && line.BaseLine.KVLevel.VisibilityThreshold < line.BaseLine.LinePercentage) { return(false); } if (line.BaseLine.KVLevel.VisibilityThreshold < 0f && -line.BaseLine.KVLevel.VisibilityThreshold > line.BaseLine.LinePercentage) { return(false); } return(true); }
private void OnSelectedItemsChanged(SelectionChangedEventArgs args) { //Logic - by default when items scroll out of view they are no longer selected. //this is because the panel is virtualised and and automatically unselected due //to the control thinking that the item is not longer part of the overall collection if (_isSelecting) { return; } try { _isSelecting = true; _selected.Edit(innerList => { var toAdd = args.AddedItems.OfType <LineProxy>().ToList(); //may need to track if last selected is off the page: var isShiftKeyDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift); //get the last item at then end of the list if (!isShiftKeyDown) { //if mouse down, we need to prevent items being cleated //add items to list foreach (var lineProxy in toAdd) { if (innerList.Contains(lineProxy)) { continue; } _lastSelected = lineProxy; innerList.Add(lineProxy); } } else { //if shift down we need to override selected and manually select our selves var last = _lastSelected.Index; var allSelectedItems = _selector.SelectedItems.OfType <LineProxy>().ToArray(); var currentPage = _selector.Items.OfType <LineProxy>().ToArray(); //1. Determine whether all selected items are on the current page [plus whether last is on the current page] var allOnCurrentPage = allSelectedItems.Intersect(currentPage).ToArray(); var lastInONcurrentPage = currentPage.Contains(_lastSelected); if (lastInONcurrentPage && allOnCurrentPage.Length == allSelectedItems.Length) { innerList.Clear(); innerList.AddRange(allSelectedItems); return; } args.Handled = true; var maxOfRecent = toAdd.Max(lp => lp.Index); int min; int max; if (last < maxOfRecent) { min = last; max = maxOfRecent; } else { min = maxOfRecent; max = last; } //maintain selection _selector.SelectedItems.Clear(); var fromCurrentPage = _selector.Items.OfType <LineProxy>() .Where(lp => lp.Index >= min && lp.Index <= max) .ToArray(); var fromPrevious = _recentlyRemovedFromVisibleRange .Items.Where(lp => lp.Index >= min && lp.Index <= max) .ToArray(); _recentlyRemovedFromVisibleRange.Clear(); //maintain our record innerList.Clear(); innerList.AddRange(fromCurrentPage); foreach (var previous in fromPrevious) { if (!innerList.Contains(previous)) { innerList.Add(previous); } } //finally reload the actual selection: foreach (var item in innerList) { _selector.SelectedItems.Add(item); } } }); } catch (Exception ex) { _logger.Error(ex, "There has been a problem with manual selection"); } finally { _isSelecting = false; } }
private void UpdateAndDrawFlowArrow(RenderTime time, LineProxy proxy, int zoomLevel, MM_DisplayParameter displayOptions, SharpDX.Direct2D1.Brush brush) { //Now, draw the line as appropriate if (proxy.Coordinates == null || proxy.Coordinates.Count == 0) { return; } // reset if bad if (proxy.FlowPositionPercentage > 1) { proxy.FlowPositionPercentage = 1; } if (proxy.FlowPositionPercentage < float.Epsilon) { proxy.FlowPositionPercentage = 0; } // reset if bad if (proxy.FlowVarPositionPercentage > 1) { proxy.FlowVarPositionPercentage = 1; } if (proxy.FlowVarPositionPercentage < float.Epsilon) { proxy.FlowVarPositionPercentage = 0; } var Line = proxy.BaseLine; // don't render dead lines flow arrows if (Line == null || Math.Abs(Line.MVAFlow) < 0.1 || (Line.NearBus != null && Line.NearBus.Dead) || (Line.FarBus != null && Line.FarBus.Dead)) { return; } //Determine how large our arrow should be float baseSize = proxy.BaseLine.KVLevel.MVASize; float threshold = proxy.BaseLine.KVLevel.MVAThreshold / 100.0f; bool flowKvVisible = proxy.BaseLine.KVLevel.ShowMVA; float mvaSize = Line.KVLevel.MVASize; float lineWidth = displayOptions.Width; float flowIncrement = 0; float flowVarIncrement = 0; float flowSize; bool isTie = Line is MM_Tie; if ((!MM_Repository.OverallDisplay.ShowLineFlows || !flowKvVisible) && !(isTie && MM_Repository.OverallDisplay.TieFlowDirectionVisible)) { return; } //MM_Repository.OverallDisplay. // absolute vs % limit bool absoluteValueFlowSize = zoomLevel < MM_Repository.OverallDisplay.LineFlows; if (isTie && MM_Repository.OverallDisplay.TieFlowDirectionVisible) { // show enhanced size/color for AC Tie lines if TieFlowDirectionVisible == true if (MM_Repository.KVLevels.ContainsKey("Tie")) { mvaSize = MM_Repository.KVLevels["Tie"].MVASize; } else if (MM_Repository.KVLevels.ContainsKey("DCTie")) { mvaSize = MM_Repository.KVLevels["DCTie"].MVASize; } else { mvaSize = 5; } } else if (Line.KVLevel.Name.Contains("Tie")) { isTie = true; } bool moveForward = true; float zoomScale = (float)zoomLevel / MM_Repository.OverallDisplay.LineFlows; bool varForward = true; var varFlowSize = Math.Min(50, lineWidth * baseSize); if (absoluteValueFlowSize) { if (Math.Abs(Line.MVAFlow) < float.Epsilon) { flowSize = flowIncrement = 0; } else { moveForward = Line.MVAFlowDirection == Line.ConnectedStations[1]; varForward = Line.MVARFlowDirection == Line.ConnectedStations[1]; flowSize = (zoomLevel / 20f) * mvaSize * Line.MVAFlow * 0.02f; // + 1.5f * lineWidth; varFlowSize = (zoomLevel / 20f) * mvaSize * Line.MVAFlow * 0.04f; // + 1.5f * lineWidth; } } else { // relative size based on limit if (Line.NormalLimit == 0) { flowSize = flowIncrement = 0; } else { var percentLimit = Line.MVAFlow / Line.NormalLimit; var percentVar = Line.MVARFlow / Line.NormalLimit; if (percentLimit < threshold) { return; } moveForward = Line.MVAFlowDirection == Line.ConnectedStations[1]; varForward = Line.MVARFlowDirection == Line.ConnectedStations[1]; flowSize = 10f * mvaSize * percentLimit * ((float)(MathUtil.Clamp(lineWidth, 1, 3) / 2f)); varFlowSize = 30f * mvaSize * percentVar * ((float)(MathUtil.Clamp(lineWidth, 1, 3) / 2f)); } } flowSize = MathUtil.Clamp(flowSize, 0, 100); varFlowSize = MathUtil.Clamp(varFlowSize, 0, 100); if (float.IsNaN(flowSize) || flowSize < 0) { flowSize = flowIncrement = 0; varFlowSize = flowVarIncrement = 0; } else { flowIncrement = MathUtil.Clamp(0.5f * zoomScale * flowSize, -20f, 20f) * (float)time.ElapsedTime.TotalSeconds; flowVarIncrement = MathUtil.Clamp(0.5f * zoomScale * varFlowSize, -20f, 20f) * (float)time.ElapsedTime.TotalSeconds; } // scale up arrow (but not speed) based on zoom if (flowSize < lineWidth + 0.25f || proxy.Length <= 0 || (MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.HideExternalElements && !Line.IsInternal)) { return; } // Move MVA flow arrow if (moveForward) { proxy.FlowPositionPercentage += flowIncrement / proxy.Length; } else { proxy.FlowPositionPercentage -= flowIncrement / proxy.Length; } if (proxy.FlowPositionPercentage < float.Epsilon) { proxy.FlowPositionPercentage = 1 - proxy.FlowPositionPercentage; } else { proxy.FlowPositionPercentage -= (float)Math.Floor(proxy.FlowPositionPercentage); // just keep the decimal } // Move Var Arrow if (varForward) { proxy.FlowVarPositionPercentage += flowVarIncrement / proxy.Length; } else { proxy.FlowVarPositionPercentage -= flowVarIncrement / proxy.Length; } if (proxy.FlowVarPositionPercentage < float.Epsilon) { proxy.FlowVarPositionPercentage = 1 - proxy.FlowVarPositionPercentage; } else { proxy.FlowVarPositionPercentage -= (float)Math.Floor(proxy.FlowVarPositionPercentage); // just keep the decimal } if (zoomLevel < MM_Repository.OverallDisplay.LineFlows) { proxy.FlowPositionPercentage = 0.5f; proxy.FlowVarPositionPercentage = 0.5f; } SolidColorBrush borderBrush = null; if (isTie && MM_Repository.OverallDisplay.TieFlowDirectionVisible) { bool importing = (Line.Substation1.IsInternal && (Line.MVAFlowDirection == Line.Substation1)) || (Line.Substation2.IsInternal && (Line.MVAFlowDirection == Line.Substation2)); var color = importing ? MM_Repository.OverallDisplay.TieFlowImportColor : MM_Repository.OverallDisplay.TieFlowExportColor; if (proxy.BlackStartDim) { color = MM_Repository.OverallDisplay.BlackstartDim(color); } borderBrush = Surface.Brushes.GetBrush(color); } // add border around flow arrow for tie //proxy.FlowPositionPercentage = 0; float rotAngle = 0; RawVector2 ArrowTip = proxy.GetPosition(proxy.FlowPositionPercentage, out rotAngle); float varrotAngle = 0; RawVector2 varArrowTip = proxy.GetPosition(proxy.FlowVarPositionPercentage, out varrotAngle); //var if (MM_Repository.OverallDisplay.VarFlows) { DrawArrow(null, brush, varArrowTip, varrotAngle, varFlowSize, varForward, 0.1f); } // mva DrawArrow(brush, borderBrush, ArrowTip, rotAngle, flowSize, moveForward, 0.25f); }
/// <summary> /// Rebuild our collection of lines to render /// </summary> /// <param name="updateTime">Time since last update.</param> /// <remarks>include base.Update(renderTime); in overloads to preserve updating UpdateTime field.</remarks> public override void Update(RenderTime updateTime) { base.Update(updateTime); if (!Surface.IsDirty && _lastZoom == Surface.Coordinates.ZoomLevel) { return; } _lastZoom = Surface.Coordinates.ZoomLevel; //_lineRenderProxies.Clear(); //_multiLines.Clear(); var lines = MM_Repository.Lines.Values.OrderBy(l => l.KVLevel.Nominal); Dictionary <string, int> lineStationMap = null; //_multiLines = new Dictionary<string, MultiLineProxy>(); bool updateMultiLine = (_multiLines.Count == 0 || lastLineCount != MM_Repository.Lines.Count); lastLineCount = MM_Repository.Lines.Count; if (updateMultiLine) { lineStationMap = new Dictionary <string, int>(); } foreach (var line in lines) { // checks to determine if we want to render this line if (line.IsZBR && line.Length > 150) // skip zbr { continue; } // skip ties // if (line.ElemType.Name == "Tie") // continue; // validations passed, calculate render info LineProxy proxy; if (!_lineRenderProxies.TryGetValue(line.TEID, out proxy)) { proxy = new LineProxy { BaseLine = line, Coordinates = new List <RawVector2>(line.Coordinates.Count) }; _lineRenderProxies.Add(line.TEID, proxy); } LineProxy.CalculateCoords(proxy, line, _lastZoom); proxy.BlackStartDim = proxy.BlackStartHidden = false; // calculate blackstart parameters if ((MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.HideNonOperatorElements || MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.DimNonOperatorElements) && (line.Operator == null || !line.Operator.Equals(MM_Repository.OverallDisplay.DisplayCompany))) { if (MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.HideNonOperatorElements) { proxy.BlackStartHidden = true; } else { proxy.BlackStartDim = true; } } else if ((MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.HideNonBlackstartElements || MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.DimNonBlackstartElements) && !line.IsBlackstart) { if (MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.HideNonBlackstartElements) { proxy.BlackStartHidden = true; } else { proxy.BlackStartDim = true; } } else if ((MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.HideExternalElements || MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.DimExternalElements) && !line.IsInternal) { if (MM_Repository.OverallDisplay.BlackstartMode == MM_Display.enumBlackstartMode.HideExternalElements) { proxy.BlackStartHidden = true; } else { proxy.BlackStartDim = true; } } // update multilines if (updateMultiLine) { // fast multiline detection int sub1Teid = line.Substation1.TEID; int sub2Teid = line.Substation2.TEID; if (sub2Teid < sub1Teid) { sub1Teid = line.Substation2.TEID; sub2Teid = line.Substation1.TEID; } string subTEIDToken = String.Format("{0:0}_{1:0}", sub1Teid, sub2Teid); int otherMultiTeid; if (lineStationMap.TryGetValue(subTEIDToken, out otherMultiTeid)) { // multiline! MultiLineProxy multi; if (!_multiLines.TryGetValue(subTEIDToken, out multi)) { // doesn't exist, add both lines multi = new MultiLineProxy(); multi.Lines.Add(_lineRenderProxies[otherMultiTeid]); _multiLines.Add(subTEIDToken, multi); } if (multi.Lines.All(l => l.BaseLine != proxy.BaseLine)) { multi.Lines.Add(proxy); } } else { lineStationMap.Add(subTEIDToken, line.TEID); } } } if (lineStationMap != null) { lineStationMap.Clear(); } lineStationMap = null; }
private void ClearAllSelections() { _selected.Clear(); _recentlyRemovedFromVisibleRange.Clear(); _lastSelected = null; }
private void OnSelectedItemsChanged(SelectionChangedEventArgs args) { //Logic - by default when items scroll out of view they are no longer selected. //this is because the panel is virtualised and and automatically unselected due //to the control thinking that the item is not longer part of the overall collection if (_isSelecting) return; try { _isSelecting = true; _selected.Edit(innerList => { var toAdd = args.AddedItems.OfType<LineProxy>().ToList(); //may need to track if last selected is off the page: var isShiftKeyDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift); //get the last item at then end of the list if (!isShiftKeyDown) { //if mouse down, we need to prevent items being cleated //add items to list foreach (var lineProxy in toAdd) { if (innerList.Contains(lineProxy)) continue; _lastSelected = lineProxy; innerList.Add(lineProxy); } } else { //if shift down we need to override selected and manually select our selves var last = _lastSelected.Index; var allSelectedItems = _selector.SelectedItems.OfType<LineProxy>().ToArray(); var currentPage = _selector.Items.OfType<LineProxy>().ToArray(); //1. Determine whether all selected items are on the current page [plus whether last is on the current page] var allOnCurrentPage = allSelectedItems.Intersect(currentPage).ToArray(); var lastInONcurrentPage = currentPage.Contains(_lastSelected); if (lastInONcurrentPage && allOnCurrentPage.Length == allSelectedItems.Length) { innerList.Clear(); innerList.AddRange(allSelectedItems); return; } args.Handled = true; var maxOfRecent = toAdd.Max(lp => lp.Index); int min; int max; if (last < maxOfRecent) { min = last; max = maxOfRecent; } else { min = maxOfRecent; max = last; } //maintain selection _selector.SelectedItems.Clear(); var fromCurrentPage = _selector.Items.OfType<LineProxy>() .Where(lp => lp.Index >= min && lp.Index <= max) .ToArray(); var fromPrevious = _recentlyRemovedFromVisibleRange .Items.Where(lp => lp.Index >= min && lp.Index <= max) .ToArray(); _recentlyRemovedFromVisibleRange.Clear(); //maintain our record innerList.Clear(); innerList.AddRange(fromCurrentPage); foreach (var previous in fromPrevious) { if (!innerList.Contains(previous)) innerList.Add(previous); } //finally reload the actual selection: foreach (var item in innerList) { _selector.SelectedItems.Add(item); } } }); } catch (Exception ex) { _logger.Error(ex,"There has been a problem with manual selection"); } finally { _isSelecting = false; } }
/// <summary> /// Creats a <see cref="PathGeometry"/> from a collection of GPS <see cref="PointF"/>s. This object should be disposed. /// </summary> /// <param name="lngLats">GPS Coordinates.</param> /// <param name="closed">Close the geometry.</param> /// <param name="filled">Fill the geometry.</param> /// <returns>IDisposable Object</returns> public PathGeometry CreateRegionPathGeometry(IList <Vector2> xy, out RawRectangleF bounds, bool closed = true, bool filled = false, bool simplify = false, float compression = 0.1f, float scaleX = 1f, float scaleY = 1f) { PathGeometry geometry = new PathGeometry(Factory2D); int pnts = 0; Vector2 scaleVector = new Vector2(scaleX, scaleY); if (xy.Count > 0) { var point = xy[0]; if (Math.Abs(scaleX - 1f) > float.Epsilon || Math.Abs(scaleY - 1f) > float.Epsilon) { point *= scaleVector; } var prev = point; float minX = point.X; float minY = point.Y; float maxX = point.X; float maxY = point.Y; using (var sink = geometry.Open()) { sink.SetFillMode(SharpDX.Direct2D1.FillMode.Winding); sink.BeginFigure(point, filled ? FigureBegin.Filled : FigureBegin.Hollow); int count = xy.Count; for (int i = 1; i < count; i++) { // compression if (simplify && i != count - 1) // don't compress last point { // linear compression var next = xy[i + 1]; bool isLinear = LineProxy.HitTestLineSegmentF(xy[i].X, xy[i].Y, prev.X, prev.Y, next.X, next.Y, compression); // distance compression float d2 = LineProxy.DistanceSquared(xy[i].X, xy[i].Y, prev.X, prev.Y); if (isLinear || d2 < compression) { continue; } } if (Math.Abs(scaleX - 1f) > float.Epsilon || Math.Abs(scaleY - 1f) > float.Epsilon) { point = xy[i] * scaleVector; } else { point = xy[i]; } sink.AddLine(point); if (point.X < minX) { minX = point.X; } if (point.X > maxX) { maxX = point.X; } if (point.Y < minY) { minY = point.Y; } if (point.Y > maxY) { maxY = point.Y; } prev = xy[i]; } sink.EndFigure(closed ? FigureEnd.Closed : FigureEnd.Open); sink.Close(); } bounds = new RawRectangleF(minX, minY, maxX, maxY); } else { bounds = new RawRectangleF(0, 0, 0, 0); } return(geometry); }