내 빠른 해결책. 여러면에서 이상적이지는 않지만 처음에는 저에게 효과적입니다. 필요한 경우 쉽게 성능을 위해 리팩토링 할 수 있습니다.
/// <summary>
/// Provides basic hit testing
/// </summary>
public class RadarHitTestUtility
{
public Dictionary<Tuple<int,int>, HitContainer> HitStorage = new Dictionary<Tuple<int, int>, HitContainer>();
public void AddEllipse(RadarObject radarObject, Point point, double x, double y)
{
// Geometry used for hit testing
var elipse = new EllipseGeometry
{
Center = point,
RadiusX = x,
RadiusY = y,
};
var key = new Tuple<int, int>((int)point.X, (int)point.Y);
var hit = new HitContainer
{
Geometry = elipse,
Bounds = elipse.Bounds,
RadarObject = radarObject
};
if(!HitStorage.ContainsKey(key))
HitStorage.Add(key, hit);
}
/// <summary>
/// Gets first radar object whose center point is within distance of point.
/// </summary>
public HitContainer GetSimpleHit(Point point, int distance = 5)
{
foreach (var hit in HitStorage)
{
if (Math.Abs(hit.Key.Item1 - point.X) <= distance && Math.Abs(hit.Key.Item2 - point.Y) <= distance)
{
hit.Value.Intersection = IntersectionDetail.NotCalculated;
return hit.Value;
}
}
return default(HitContainer);
}
/// <summary>
/// Gets first radar object that contains point
/// </summary>
public HitContainer GetHit(Point point)
{
var PreCheckDistance = 50;
foreach (var hit in HitStorage)
{
if (Math.Abs(hit.Key.Item1 - point.X) <= PreCheckDistance && Math.Abs(hit.Key.Item2 - point.Y) <= PreCheckDistance)
{
if (hit.Value.Geometry.FillContains(point))
{
hit.Value.Intersection = IntersectionDetail.FullyInside;
return hit.Value;
}
}
}
return default(HitContainer);
}
/// <summary>
/// Gets first radar object that intersects with geometry
/// </summary>
public HitContainer GetHit(Geometry geometry)
{
var PreCheckDistance = 50;
var GeometryCheckTolerance = 1;
var center = geometry.Bounds.Center();
foreach (var hit in HitStorage)
{
if (Math.Abs(hit.Key.Item1 - center.X) <= PreCheckDistance && Math.Abs(hit.Key.Item2 - center.Y) <= PreCheckDistance)
{
var result = hit.Value.Geometry.FillContainsWithDetail(geometry, GeometryCheckTolerance, ToleranceType.Absolute);
if (result != IntersectionDetail.Empty)
{
hit.Value.Intersection = result;
return hit.Value;
}
}
}
return default(HitContainer);
}
public class HitContainer
{
public RadarObject RadarObject { get; set; }
public Geometry Geometry { get; set; }
public Rect Bounds { get; set; }
public IntersectionDetail Intersection { get; set; }
}
public void Clear()
{
HitStorage.Clear();
}
}
은 제어
public RadarHitTestUtility HitTester = new RadarHitTestUtility();
당신은 현재의 객체가 히트 테스트 컬렉션의 존재 때문에 어떤 점에서 지우기()를 호출해야합니다에서 인스턴스를 선언합니다.
의 OnRender()는 무승부 호출이 히트 테스트 목적으로 기록 할 때 내가 히트 검사를 요구하고 어떻게
다음
HitTester.AddEllipse(radarObject, radarObject.Point, actorRadius, actorRadius);
이야) (AddEllipse와 함께 녹음 할 수 있습니다에서
HitTester.Clear();
private void MouseDownHandler(object sender, MouseButtonEventArgs e)
{
IsMouseDown = true;
Cursor = Cursors.Hand;
DragInitialPosition = Mouse.GetPosition(this);
DragInitialPanOffset = CanvasData.PanOffset;
var hit = FindElementUnderClick(sender, e);
if (hit != null)
{
SelectedItem = hit.RadarObject.Actor;
}
}
private RadarHitTestUtility.HitContainer FindElementUnderClick(object sender, MouseEventArgs e)
{
var position = e.GetPosition((UIElement)sender);
return HitTester.GetHit(position);
}
타원 이외의 모양을 테스트하려면 RadarHitTestUtility에 적절한 녹음 방법을 추가하고 호출하여 다른 종류의 기하학을 만들어 테스트합니다. ainst.
귀하의 확인과 설명에 감사드립니다. : –
미안 OP의 질문을 오해하지 않는 한,이 것은 정확하지 않습니다. –
OP는 그가 DrawingContext 또는 DrawingContext를 사용하여 그리는 원과 같은 다른 것을 사용하여 그리는 직사각형에 마우스가 닿는 것을 알고 싶어합니다. 그래서, 어떻게 할 수있는 방법을 찾았습니까? – bitbonk