It's really quite simple. Two ranges do not overlap if the largest of the minimums is greater than the smallest of the maximums. For example, if you have Min1-Max1 and Min2-Max2 as your ranges then there is no overlap if Max(Min1,Min2) > Min(Max1,Max2).
Here's a way too complex demo of this algorithm in action. Start a new WPF application project and call it Overlap. Target any Framework from 3.5 onward.
MainWindow.xaml uses a canvas and looks like this...
<Window x:Class="Overlap.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:OverlappingDates"
mc:Ignorable="d" ResizeMode="NoResize"
Title="Overlapping
Ranges" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Canvas Background="AliceBlue" MouseMove="Canvas_MouseMove" MouseUp="Canvas_MouseUp" MouseLeave="Canvas_MouseLeave">
<TextBlock Canvas.Left="10" Canvas.Top="10" Text="{Binding Line1Start, StringFormat='Min: {0}'}"/>
<Line X1="{Binding Line1Start}" X2="{Binding Line1End}" Y1="30" Y2="30" Stroke="Red" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeThickness="10" MouseLeftButtonDown="Line1_MouseLeftButtonDown"/>
<TextBlock Canvas.Left="450" Canvas.Top="10" Text="{Binding Line1End,StringFormat='Max: {0}'}"/>
<TextBlock Canvas.Left="10" Canvas.Top="70" Text="{Binding Line2Start, StringFormat='Min: {0}'}"/>
<Line X1="{Binding Line2Start}" X2="{Binding Line2End}" Y1="90" Y2="90" Stroke="Green" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeThickness="10" MouseLeftButtonDown="Line2_MouseLeftButtonDown"/>
<TextBlock Canvas.Left="450" Canvas.Top="70" Text="{Binding Line2End, StringFormat='Max: {0}'}"/>
<TextBlock Canvas.Left="10" Canvas.Top="120" Text="{Binding Path=MaxMin, StringFormat='Maximum Min value is
{0}'}"/>
<TextBlock Canvas.Left="10" Canvas.Top="140" Text="{Binding Path=MinMax, StringFormat='Minimum Max value is {0}'}"/>
<TextBlock Canvas.Left="10" Canvas.Top="160" Text="{Binding Path=Overlap, StringFormat='Max(Min1,Min2) less than or equal
to Min(Max1,Max2) = Ranges overlap: {0}'}"/>
<TextBlock Canvas.Left="10" Canvas.Top="250" Text="Click and drag the ends of the lines to see the algorithm in
action" FontWeight="Bold"/>
</Canvas>
</Window>
Most of the code behind is involved in the graphics. It looks like this. I have bolded the three lines that are important.
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace Overlap
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public Double Line1Start
{
get { return
_Line1Start; }
set
{
SetProperty(ref _Line1Start, value);
OnPropertyChanged("MaxMin");
}
}
public Double Line1End
{
get { return
_Line1End; }
set
{
SetProperty(ref _Line1End, value);
OnPropertyChanged("MinMax");
}
}
private Double _Line1Start = 25;
private Double _Line1End = 475;
public Double Line2Start
{
get { return
_Line2Start; }
set
{
SetProperty(ref _Line2Start, value);
OnPropertyChanged("MaxMin");
}
}
public Double Line2End
{
get { return
_Line2End; }
set
{
SetProperty(ref _Line2End, value);
OnPropertyChanged("MinMax");
}
}
private Double _MinMax;
public Double MinMax
{
get
{
_MinMax = Math.Min(Line1End, Line2End);
OnPropertyChanged("Overlap");
return _MinMax;
}
}
private Double _MaxMin;
public double MaxMin
{
get
{
_MaxMin = Math.Max(Line1Start, Line2Start);
OnPropertyChanged("Overlap");
return _MaxMin;
}
}
public string Overlap
{
get { return (_MaxMin
<= _MinMax ? "True" : "False"); }
}
private Double _Line2Start = 25;
private Double _Line2End = 475;
private Point PriorMousePosition;
private bool
TrackingLine1Start = false;
private bool
TrackingLine1End = false;
private bool
TrackingLine2Start = false;
private bool
TrackingLine2End = false;
public event PropertyChangedEventHandler
PropertyChanged;
protected bool
SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
private void
OnPropertyChanged(String PropertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
public MainWindow()
{
InitializeComponent();
}
private void
Line1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
PriorMousePosition = Mouse.GetPosition(this);
if (PriorMousePosition.X > Line1Start + (Line1End - Line1Start) /
2)
TrackingLine1End = true;
else
TrackingLine1Start = true;
}
private void
Line2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
PriorMousePosition = Mouse.GetPosition(this);
if (PriorMousePosition.X > Line2Start + (Line2End - Line2Start) /
2)
TrackingLine2End = true;
else
TrackingLine2Start = true;
}
private void
Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
StopTracking();
}
private void
Canvas_MouseLeave(object sender, MouseEventArgs e)
{
StopTracking();
}
private void
StopTracking()
{
TrackingLine1End = false;
TrackingLine1Start = false;
TrackingLine2End = false;
TrackingLine2Start = false;
}
private void
Canvas_MouseMove(object sender, MouseEventArgs e)
{
double DeltaX = Mouse.GetPosition(this).X -
PriorMousePosition.X;
if (TrackingLine1Start)
{
Line1Start += DeltaX;
if (Line1Start < 25) Line1Start = 25;
if (Line1Start > Line1End - 10) Line1Start = Line1End - 10;
}
if (TrackingLine1End)
{
Line1End += DeltaX;
if (Line1End > 475) Line1End = 475;
if (Line1End < Line1Start + 10) Line1End = Line1Start + 10;
}
if (TrackingLine2Start)
{
Line2Start += DeltaX;
if (Line2Start < 25) Line2Start = 25;
if (Line2Start > Line2End - 10) Line2Start = Line2End - 10;
}
if (TrackingLine2End)
{
Line2End += DeltaX;
if (Line2End > 475) Line2End = 475;
if (Line2End < Line2Start + 10) Line2End = Line2Start + 10;
}
PriorMousePosition = Mouse.GetPosition(this);
}
}
}
No comments:
Post a Comment