Search code examples
c++gtkgtkmm

Selecting drawn lines when clicked on in a gtk drawingarea


I'll note here that I'm not really an advanced programmer. I'm more of a mathematician, so in the process of designing this application I'm learning how to work with particular elements of C++. I can follow algorithms and examples and whatnot very easily, I just don't have a very good mental catalogue of C++ tools.

The idea of the program is captured in the image below. You can place, select and move the nodes. The currently selected node is in red (and you can select more than one). I've implemented this using gtkmm and the drawingarea widget. When you click on the drawing area, the program calculates the closest grid intersection point and if there is a node there it selects it.

The nodes are stored in an unordered_map with a Coordinate struct as the key. Lines are stored in an unordered_map with a pair for the key. Using this I can easily check if a node exists at a point, but it's not so easy to check if a line passes through a point.

I want to be able to make lines selectable too. I can't think of an efficient way to manage this similarly as for nodes: I can't just snap the pointer's coordinates to the nearest line because that would require me to iterate through every line in the program, then check if the pointer was near enough to the line, if not proceed to the next, which would get very inefficient as the number of lines grows.

Here's an image as an example: https://i.sstatic.net/Nfrht.png

Is there some way to perhaps add an object to the GTK drawing area that sends out a signal when clicked?

Edit: It's straightforward mathematically to determine if, given a line and a coordinate, that coordinate exists on the line. However, I'm dealing with arbitrarily many lines so the main issue is determining which line is nearest


Solution

  • What you need is a canvas widget rather than a basic GtkDrawingArea where you'd have to do the click handling yourself.

    The best option appears to be GooCanvas which comes with c++ bindings

    If, however, you do proceed with GtkDrawingArea yourself, there are a number of ways that you can store the data to cut down on the number of lines you need to check for each point, for example you could store the points in a QuadTree.