/// <summary> /// Draw all the available labels onto the screen (drawArea). /// </summary> /// <param name="drawArea">The area we are drawing on</param> public void Draw(DrawArea drawArea) { this.drawArea = drawArea; if (!Properties.Settings.Default.showLabels) { return; } float closestDistanceSquared = float.MaxValue; foreach (StorableLabel label in labels.Labels) { if (!dragging || !label.Equals(draggingLabelToReplace)) { DrawLabel(label); } float distanceSquared = (float)WorldLocation.GetDistanceSquared2D(label.WorldLocation, drawArea.MouseLocation); if (distanceSquared < closestDistanceSquared) { closestDistanceSquared = distanceSquared; closestToMouseLabel = label; } } if (dragging) { DrawLabel(draggingLabel); } }
/// <summary> /// Check wether this vector node is closest to the mouse location /// </summary> /// <param name="location">Location to check</param> /// <param name="mouseLocation">Current mouse location</param> /// <param name="trackNode">The trackNode that will be stored when indeed it is the closest to the mouse location</param> /// <param name="vectorSection">the vectorSection that will be stored when indeed it is closest to the mouse location</param> /// <param name="tvsi">Current index of the trackvectorsection</param> /// <param name="pixelsPerMeter"></param> public void CheckMouseDistance(WorldLocation location, WorldLocation mouseLocation, TrackNode trackNode, TrVectorSection vectorSection, int tvsi, double pixelsPerMeter) { storedMouseLocation = mouseLocation; float distanceSquared = WorldLocation.GetDistanceSquared2D(location, mouseLocation); // to make unique distances becasue they also act as Key double distanceSquaredIndexed = ((double)distanceSquared) * (1 + 1e-16 * trackNode.Index); if (distanceSquaredIndexed < sortedTrackCandidates.First().Key) { if (!sortedTrackCandidates.ContainsKey(distanceSquaredIndexed)) { sortedTrackCandidates.Add(distanceSquaredIndexed, new TrackCandidate(trackNode, vectorSection, tvsi, 0)); // The next one is a bit tricky. The problem is that the first culling is done based on the trackvector section location // Which is only at one side of the section. So the other end might be quiet far away. // Unfortunately, this means that we need to keep track of many candidates to make sure we can calculate the closest one // Which is costing performance. // The biggest issue is for a long track close to a region with lots junctions and hence small track segments // By making this number zoom dependent, we get good results for big zooms, and not a large // performance penalty for wide views int maxNumberOfCandidates = 50 + (int)(100 * pixelsPerMeter); while (sortedTrackCandidates.Count > maxNumberOfCandidates) { sortedTrackCandidates.RemoveAt(0); // First one has largest distance } } } }
/// <summary> /// Check wether this trackNode (assumed to be a junction or endnode) is closest to the mouse location /// </summary> /// <param name="location">Location to check</param> /// <param name="mouseLocation">Current mouse location</param> /// <param name="junctionOrEndNode">the trackNode that will be stored when it is indeed the closest</param> /// <param name="description">The type of item (needed for later printing in statusbar)</param> public void CheckMouseDistance(WorldLocation location, WorldLocation mouseLocation, TrackNode junctionOrEndNode, string description) { float distanceSquared = WorldLocation.GetDistanceSquared2D(location, mouseLocation); if (distanceSquared < ClosestDistanceSquared) { ClosestDistanceSquared = distanceSquared; this.JunctionOrEndNode = junctionOrEndNode; this.Description = description; } }
/// <summary> /// Check wether this track Item is closest to the mouse location /// </summary> /// <param name="location">Location to check</param> /// <param name="mouseLocation">Current mouse location</param> /// <param name="trItem">The track Item that will be stored when it is indeed the closest</param> public void CheckMouseDistance(WorldLocation location, WorldLocation mouseLocation, DrawableTrackItem trItem) { float distanceSquared = WorldLocation.GetDistanceSquared2D(location, mouseLocation); if (distanceSquared < ClosestDistanceSquared) { ClosestDistanceSquared = distanceSquared; this.DrawableTrackItem = trItem; this.worldLocation = location; this.Description = trItem.Description; } }
/// <summary> /// Find the node in the path that is closest to the mouse, /// </summary> /// <param name="drawArea">Area that is being drawn upon and where we have a mouse location</param> /// <param name="drawnPathData">The data structure with the information on the drawn path</param> private void FindActiveNode(DrawArea drawArea, DrawnPathData drawnPathData) { // Initial simplest implementation: find simply the closest and first. float closestMouseDistanceSquared = float.MaxValue; TrainpathNode closestNode = null; foreach (TrainpathNode node in drawnPathData.DrawnNodes) { float distanceSquared = (float)WorldLocation.GetDistanceSquared2D(node.Location, drawArea.MouseLocation); // by using '<=' instead of '<' we should get the latest one, which overrides earlier ones // To prevent numerical issues, we add a small number (smaller than two junctions would normally be together if (distanceSquared <= closestMouseDistanceSquared + 0.1f) { closestMouseDistanceSquared = distanceSquared; closestNode = node; } } activeNode = closestNode; }