Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Polygon Select to the Lasso tool #1096

Open
Acyone opened this issue Nov 8, 2024 Discussed in #610 · 2 comments
Open

Add Polygon Select to the Lasso tool #1096

Acyone opened this issue Nov 8, 2024 Discussed in #610 · 2 comments

Comments

@Acyone
Copy link
Contributor

Acyone commented Nov 8, 2024

Description

When using the lasso tool, crtl-clicking or shift-clicking a point would draw the selection in a straight line from the last selected point to the next.

This would :

  • allow selection of polygonal shapes with perfect edges
  • make selecting precise shapes easier
  • speed up rough selections

Additional context

Discussed in #610

Originally posted by enderpuff December 15, 2023
Pretty self explanatory, but polygon selects are very very useful for editing images, for stuff like isolating objects or removing backgrounds, etc...

@cameronwhite
Copy link
Member

Doing this as part of the lasso tool sounds reasonable to me 👍

There could also be an option in the toolbar to switch between the two modes, as an alternative idea to the ctrl/shift hotkeys

@cameronwhite cameronwhite marked this as a duplicate of #1278 Feb 22, 2025
@Mtothexmax
Copy link

Mtothexmax commented Feb 23, 2025

Here is the untested source code made with an LLM

using System;
using System.Collections.Generic;
using Cairo;
using ClipperLib;
using Pinta.Core;

namespace Pinta.Tools;

public sealed class LassoSelectTool : BaseTool
{
    private readonly IWorkspaceService workspace;

    private bool is_drawing = false;
    private CombineMode combine_mode;
    private SelectionHistoryItem? hist;
    private List<IntPoint> polygon_points = new List<IntPoint>();

    public LassoSelectTool(IServiceProvider services) : base(services)
    {
        workspace = services.GetService<IWorkspaceService>();
    }

    public override string Name => Translations.GetString("Lasso Select");
    public override string Icon => Pinta.Resources.Icons.ToolSelectLasso;
    public override string StatusBarText => Translations.GetString("Click to set points for a polygonal selection area. Click near the starting point to close the selection.");
    public override Gdk.Key ShortcutKey => new(Gdk.Constants.KEY_S);
    public override Gdk.Cursor DefaultCursor => Gdk.Cursor.NewFromTexture(Resources.GetIcon("Cursor.LassoSelect.png"), 9, 18, null);
    public override int Priority => 17;

    protected override void OnBuildToolBar(Gtk.Box tb)
    {
        base.OnBuildToolBar(tb);
        workspace.SelectionHandler.BuildToolbar(tb, Settings);
    }

    protected override void OnMouseDown(Document document, ToolMouseEventArgs e)
    {
        PointD pd = document.ClampToImageSize(e.PointDouble);
        IntPoint ip = new IntPoint((long)Math.Round(pd.X), (long)Math.Round(pd.Y));

        if (!is_drawing)
        {
            hist = new SelectionHistoryItem(workspace, Icon, Name);
            hist.TakeSnapshot();
            combine_mode = workspace.SelectionHandler.DetermineCombineMode(e);
            polygon_points.Clear();
            polygon_points.Add(ip);
            is_drawing = true;
            document.PreviousSelection = document.Selection.Clone();
        }
        else
        {
            polygon_points.Add(ip);
            if (polygon_points.Count >= 3 && SquaredDistance(polygon_points[polygon_points.Count - 1], polygon_points[0]) < 25)
            {
                polygon_points.RemoveAt(polygon_points.Count - 1);
                document.Selection.SelectionPolygons.Clear();
                document.Selection.SelectionPolygons.Add(polygon_points);
                SelectionModeHandler.PerformSelectionMode(document, combine_mode, document.Selection.SelectionPolygons);
                if (hist != null)
                {
                    document.History.PushNewItem(hist);
                    hist = null;
                }
                is_drawing = false;
                polygon_points.Clear();
            }
        }
    }

    protected override void OnMouseMove(Document document, ToolMouseEventArgs e)
    {
        if (!is_drawing)
            return;

        PointD pd = document.ClampToImageSize(e.PointDouble);
        IntPoint ip = new IntPoint((long)Math.Round(pd.X), (long)Math.Round(pd.Y));
        List<IntPoint> temp_polygon = new List<IntPoint>(polygon_points);
        temp_polygon.Add(ip);

        document.Selection.SelectionPolygons.Clear();
        document.Selection.SelectionPolygons.Add(temp_polygon);
        SelectionModeHandler.PerformSelectionMode(document, combine_mode, document.Selection.SelectionPolygons);
        document.Workspace.Invalidate();
    }

    protected override void OnMouseUp(Document document, ToolMouseEventArgs e)
    {
        // No action needed for polygon lasso
    }

    private static long SquaredDistance(IntPoint a, IntPoint b)
    {
        long dx = a.X - b.X;
        long dy = a.Y - b.Y;
        return dx * dx + dy * dy;
    }
}

Can someone please try it?

Replace the LassoSelectTool for a quick test but create both as tools and call this one PolygonLassoSelectTool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants