Skip to content

Commit

Permalink
Hit testing and selection
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Vardeman committed Jan 1, 2021
1 parent 759a055 commit 5aeec83
Show file tree
Hide file tree
Showing 23 changed files with 560 additions and 52 deletions.
15 changes: 14 additions & 1 deletion src/TopoPad.AvaloniaSceneInteraction/EventArgs/InputConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,20 @@ public static TP.PointerType Convert(PointerType value)

public static TP.PointerUpdateKind Convert(PointerUpdateKind value)
{
return (TP.PointerUpdateKind)value;
return value switch
{
PointerUpdateKind.LeftButtonPressed => TP.PointerUpdateKind.LeftButtonPressed,
PointerUpdateKind.LeftButtonReleased => TP.PointerUpdateKind.LeftButtonReleased,
PointerUpdateKind.MiddleButtonPressed => TP.PointerUpdateKind.MiddleButtonPressed,
PointerUpdateKind.MiddleButtonReleased => TP.PointerUpdateKind.MiddleButtonReleased,
PointerUpdateKind.RightButtonPressed => TP.PointerUpdateKind.RightButtonPressed,
PointerUpdateKind.RightButtonReleased => TP.PointerUpdateKind.RightButtonReleased,
PointerUpdateKind.XButton1Pressed => TP.PointerUpdateKind.XButton1Pressed,
PointerUpdateKind.XButton1Released => TP.PointerUpdateKind.XButton1Released,
PointerUpdateKind.XButton2Pressed => TP.PointerUpdateKind.XButton2Pressed,
PointerUpdateKind.XButton2Released => TP.PointerUpdateKind.XButton2Released,
_ => TP.PointerUpdateKind.Other
};
}

public static TP.Key Convert(Key value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See license.txt in the TopoPad distribution or repository for the
// full text of the license.

using Ardalis.GuardClauses;
using Avalonia.Input;
using NetTopologySuite.Geometries;
using TP = TopoPad.SceneInteraction.InputEvents;
Expand Down Expand Up @@ -35,9 +36,33 @@ public Coordinate Position

public PointerPointWrapper(PointerPoint p)
{
Guard.Against.Null(p, nameof(p));
P = p;
}

public override bool Equals(object obj)
{
return obj switch
{
PointerPointWrapper that => this.P == that.P,
_ => false
};
}

public override int GetHashCode()
{
return P.GetHashCode();
}

public static bool operator ==(PointerPointWrapper p1, PointerPointWrapper p2)
{
return p1.Equals(p2);
}

public static bool operator !=(PointerPointWrapper p1, PointerPointWrapper p2)
{
return !p1.Equals(p2);
}

}
}
16 changes: 16 additions & 0 deletions src/TopoPad.AvaloniaSceneInteraction/EventArgs/PointerWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See license.txt in the TopoPad distribution or repository for the
// full text of the license.

using Ardalis.GuardClauses;
using Avalonia.Input;
using TP = TopoPad.SceneInteraction.InputEvents;

Expand All @@ -19,7 +20,22 @@ public class PointerWrapper : TP.IPointer

public PointerWrapper(IPointer pointer)
{
Guard.Against.Null(pointer, nameof(pointer));
m_Pointer = pointer;
}

public override bool Equals(object obj)
{
return obj switch
{
PointerWrapper that => this.m_Pointer == that.m_Pointer,
_ => false
};
}

public override int GetHashCode()
{
return m_Pointer.GetHashCode();
}
}
}
6 changes: 4 additions & 2 deletions src/TopoPad.AvaloniaSceneInteraction/SceneControlViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ public SceneControlViewModel()
PushInteraction(new PointerWheelZoomInteraction());
PushInteraction(new ArrowKeyPanInteraction());
PushInteraction(new DragPanInteraction());
PushInteraction(new ClickSelectInteraction());
}

private void ViewChanged()
Expand Down Expand Up @@ -242,8 +243,9 @@ public IInteraction PopInteraction()
IInteraction interaction = null;
if (m_Interactions.Count > 0)
{
interaction = m_Interactions[0];
m_Interactions.RemoveAt(0);
int index = m_Interactions.Count - 1;
interaction = m_Interactions[index];
m_Interactions.RemoveAt(index);
interaction.Scene = null;
}
return interaction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.0-preview4" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.0-preview4" />
<PackageReference Include="Avalonia" Version="0.10.0-rc1" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.0-rc1" />
</ItemGroup>

<ItemGroup>
Expand Down
80 changes: 80 additions & 0 deletions src/TopoPad.Core/HitTest/ItemsHitTestSpec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using TopoPad.Core.Layers;
using TopoPad.Core.SpatialItems;

namespace TopoPad.Core.HitTest
{
public class ItemsHitTestSpec
{
private Lazy<HashSet<IItemsLayer>> m_Layers;
public HashSet<IItemsLayer> Layers => m_Layers.Value;

public bool LimitLayers { get; set; }

private Lazy<HashSet<ISpatialItem>> m_SpatialItems;
public HashSet<ISpatialItem> SpatialItems => m_SpatialItems.Value;

public bool LimitItems { get; set; }

public bool BoundaryOnly { get; set; }

public bool TopmostOnly { get; set; }

public bool SelectedItemsOnly { get; set; }

public bool ActiveItemsOnly { get; set; }

public ItemsHitTestSpec(bool boundaryOnly = false,
bool topmostOnly = false, bool selectedItemsOnly = false,
bool activeItemsOnly = false):
this(null, null, boundaryOnly, topmostOnly, selectedItemsOnly,
activeItemsOnly)
{
}

public ItemsHitTestSpec(IEnumerable<IItemsLayer> layers,
bool boundaryOnly = false,bool topmostOnly = false,
bool selectedItemsOnly = false, bool activeItemsOnly = false) :
this(layers, null, boundaryOnly, topmostOnly,
selectedItemsOnly, activeItemsOnly)
{
}

public ItemsHitTestSpec(IEnumerable<ISpatialItem> spatialItems,
bool boundaryOnly = false, bool topmostOnly = false,
bool selectedItemsOnly = false, bool activeItemsOnly = false) :
this(null, spatialItems, boundaryOnly, topmostOnly,
selectedItemsOnly, activeItemsOnly)
{
}

public ItemsHitTestSpec(IEnumerable<IItemsLayer> layers,
IEnumerable<ISpatialItem> spatialItems, bool boundaryOnly = false,
bool topmostOnly = false, bool selectedItemsOnly = false,
bool activeItemsOnly = false)
{
if (layers != null)
{
LimitLayers = true;
foreach (IItemsLayer layer in layers)
{
Layers.Add(layer);
}
}
if (spatialItems != null)
{
LimitItems = true;
foreach (ISpatialItem item in spatialItems)
{
SpatialItems.Add(item);
}
}
BoundaryOnly = boundaryOnly;
TopmostOnly = topmostOnly;
SelectedItemsOnly = selectedItemsOnly;
ActiveItemsOnly = activeItemsOnly;
}

}
}
2 changes: 1 addition & 1 deletion src/TopoPad.Core/IGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// full text of the license.

using TopoPad.Core.Layers;
using TopoPad.Core.Style;

namespace TopoPad.Core
{
Expand All @@ -18,5 +17,6 @@ public interface IGroup : IGroupNode
void RemoveChild(IGroupNode child);

void Ungroup();

}
}
46 changes: 44 additions & 2 deletions src/TopoPad.Core/IGroupNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
// full text of the license.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Transactions;
using NetTopologySuite.Geometries;
using TopoPad.Core.HitTest;
using TopoPad.Core.Layers;
using TopoPad.Core.SpatialItems;
using TopoPad.Core.Style;

namespace TopoPad.Core
Expand Down Expand Up @@ -97,5 +97,47 @@ IGroupNode FindTopMatchingChild(Func<IGroupNode, bool> nodeTester)
}
return null;
}

void HitTest(double x, double y, double viewBoundaryBuffer,
double viewToWorld, ItemsHitTestSpec spec,
Dictionary<ISpatialItem, IItemsLayer> hits)
{
foreach (IGroupNode node in ChildNodesReversed)
{
node.HitTest(x, y, viewBoundaryBuffer, viewToWorld, spec, hits);
}
}

void SelectAll()
{
foreach (IGroupNode node in ChildNodesReversed)
{
node.SelectAll();
}
}

void DeselectAll()
{
foreach (IGroupNode node in ChildNodesReversed)
{
node.DeselectAll();
}
}

void ActivateAll()
{
foreach (IGroupNode node in ChildNodesReversed)
{
node.ActivateAll();
}
}

void DeactivateAll()
{
foreach (IGroupNode node in ChildNodesReversed)
{
node.DeactivateAll();
}
}
}
}
11 changes: 11 additions & 0 deletions src/TopoPad.Core/ITranslatable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2020 Andrew Vardeman. Published under the MIT license.
// See license.txt in the TopoPad distribution or repository for the
// full text of the license.

namespace TopoPad.Core
{
public interface ITranslatable
{
public void Translate(double x, double y);
}
}
16 changes: 16 additions & 0 deletions src/TopoPad.Core/IViewport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,22 @@ Envelope WorldToView(Envelope worldEnvelope)
return worldEnvelope;
}

Coordinate ViewToWorld(Coordinate viewCoord)
{
Guard.Against.Null(viewCoord, nameof(viewCoord));
AffineTransformation transform = ViewToWorldTransform;
Coordinate worldCoord = new Coordinate();
return transform.Transform(viewCoord, worldCoord);
}

Coordinate WorldToView(Coordinate worldCoord)
{
Guard.Against.Null(worldCoord, nameof(worldCoord));
AffineTransformation transform = ViewToWorldTransform;
Coordinate viewCoord = new Coordinate();
return transform.Transform(worldCoord, viewCoord);
}

void Fit(IBoundedItem item, double paddingFraction = 0)
{
Fit(item?.Bounds, paddingFraction);
Expand Down
8 changes: 0 additions & 8 deletions src/TopoPad.Core/Layers/IItemsLayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,20 @@ public interface IItemsLayer : ILayer

void SelectItems(IEnumerable<ISpatialItem> items);

void SelectAll();

void DeselectItem(ISpatialItem item);

void DeselectItems(IEnumerable<ISpatialItem> items);

void DeselectAll();

bool IsItemSelected(ISpatialItem item);

void ActivateItem(ISpatialItem item);

void ActivateItems(IEnumerable<ISpatialItem> items);

void ActivateAll();

void DeactivateItem(ISpatialItem item);

void DeactivateItems(IEnumerable<ISpatialItem> items);

void DeactivateAll();

bool IsItemActive(ISpatialItem item);
}
}
Loading

0 comments on commit 5aeec83

Please sign in to comment.