Closed Musicted closed 7 years ago
I'd like to propose another selection policy:
Each selectable element has a bounding box or a convex hull. An intersection with that shape is easily calculated on each click.
To handle collisions with overlapping elements, there are two possibilities:
To be honest, I like my method most, because of its intuitiveness :P the number of elements per page is surely limited to some thousands max, which means that the calculation includes some thousand 'point-in-polygon' checks. This should be possible within some milliseconds, even in old machines. The shortest noticable delay for a mouse click is much longer than that
I had thought about using bounding boxes before, but that won't do with a long, diagonal wire. Its bounding box would be ginormous. This can also be true of a wire's convex hull. I think we should find all colliding polygonal elements (e.g. symbols, labels) via convex hull and the nearest linear element (e.g. wire) via control points and heuristically decide which one the user clicked on. Once a single line segment has been found, a shortest-distance-to-point calculation shouldn't be too costly. I do like the collision handling, though. Maybe a hybrid system would do the trick: single click triggers timestamp selection, click and hold triggers a context menu (I'd like to relegate view panning to Space anyway).
Okay, new idea: why not leave the selection check to the element? Every element may provide a method like 'def checkSelection(self, cursor)' which returns true if below cursor and false if not below cursor. For example: Symbols may use the convex hull then and wires are only selectable when clicked directly on the line
Well, clicking directly on a one-dimensional object is a bit of a stretch. The wire itself doesn't know how it's going to be rendered (and I'd love for the user to be able to configure wire line width on the fly), so that one's out. The best we can do is find the line closest to the mouse position, find its shortest distance to the point, and then decide (again, heuristically) whether the line was supposed to be selected. Also, multiple polygons will report a selection in the event that they overlap, so we won't be able to avoid collision handling anyway.
Well, we can also leave that check to the renderer
Because if we distinguish between wires and symbols and junctions anyway, every element should provide it's own method
Agreed, to each its own. That would entail storing the points of the representation in a different way though, because now they're stored as [x1, y1, z1, x2, y2, z2, x3, ..., xn, yn, zn] in accordance with the vertex array format.
Uhm... Why that complicated? Example for wires: the renderer knows each wire segment and the width of the wire. You could now calculate the distance of each segment with the point (orthogonal projection), check if the parallel part is within the two points and if the orthogonal point is smaller than the width. What I mean is that the vertex arrays do not need to be taken in account when doing those checks. The whole information of these things is given by the element itself
I just asked myself why the wire doesn't know its width. It should know its width, because it is an integral part of the wire. This is because the schematics have to include a full description of their look. The wire should also know its color and style. Just the logic HOW to render these properties should be in the renderer only. I think the data structure is not final yet :D I'm going to create a new issue on that case...
I think we've generally found our technique. Or rather, our diverse techniques.
Possible solutions here.