Skip to content

Commit

Permalink
Updated GUIViewObjectsHandler. Refs #13894
Browse files Browse the repository at this point in the history
  • Loading branch information
palvarezlopez committed Dec 19, 2023
1 parent 54ae80e commit 8a03a7f
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 66 deletions.
4 changes: 2 additions & 2 deletions src/netedit/GNEViewNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ GNEViewNet::getObjectsUnderCursor() const {
void
GNEViewNet::updateObjectsInBoundary(const Boundary &boundary) {
// clear post drawing elements
gViewObjectsHandler.clearElements();
gViewObjectsHandler.clearSelectedElements();
// set selection boundary in gObjectsInPosition
gViewObjectsHandler.setSelectionBoundary(boundary);
// push matrix
Expand All @@ -498,7 +498,7 @@ GNEViewNet::updateObjectsInBoundary(const Boundary &boundary) {
void
GNEViewNet::updateObjectsInPosition(const Position &pos) {
// clear post drawing elements
gViewObjectsHandler.clearElements();
gViewObjectsHandler.clearSelectedElements();
// set selection position in gObjectsInPosition
gViewObjectsHandler.setSelectionPosition(pos);
// create an small boundary
Expand Down
142 changes: 83 additions & 59 deletions src/utils/gui/div/GUIViewObjectsHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ GUIViewObjectsHandler::GUIViewObjectsHandler() {}


void
GUIViewObjectsHandler::clearElements() {
GUIViewObjectsHandler::clearSelectedElements() {
// reset recompute boundaries
recomputeBoundaries = GLO_NETWORK;
// clear objects under cursor
myElementsUnderCursor.clear();
mySelectedObjets.clear();
mySortedSelectedObjects.clear();
mySelectedObjects.clear();
// reset marked elements
markedEdge = nullptr;
markedLane = nullptr;
Expand Down Expand Up @@ -71,56 +71,78 @@ GUIViewObjectsHandler::setSelectionBoundary(const Boundary &boundary) {

bool
GUIViewObjectsHandler::isElementSelected(const GUIGlObject* GLObject) const {
return mySelectedObjets.find(GLObject) != mySelectedObjets.end();
return mySelectedObjects.find(GLObject) != mySelectedObjects.end();
}


bool
GUIViewObjectsHandler::checkBoundaryParentElement(const GUIGlObject* GLObject, const GUIGlObject* parent) {
if (!mySelectionBoundary.isInitialised()) {
return false;
}
if (parent == nullptr) {
return false;
}
auto finder = mySelectedObjects.find(parent);
if (finder != mySelectedObjects.end() && finder->second) {
return addElementUnderCursor(GLObject, true);
} else {
return false;
}
}


bool
GUIViewObjectsHandler::checkCircleElement(const GUIVisualizationSettings::Detail d, const GUIGlObject* GLObject,
const Position &center, const double radius) {
// declare squared radius
const double squaredRadius = (radius * radius);
// continue depending if we're selecting a position or a boundary
if (mySelectionBoundary.isInitialised()) {
// continue depending of detail level
if (d <= GUIVisualizationSettings::Detail::PreciseSelection) {
// make a boundary using center and radius
Boundary b;
b.add(center);
b.grow(radius);
// check if selection boundary contains the centering boundary of object
if (mySelectionBoundary.contains(GLObject->getCenteringBoundary())) {
return addElementUnderCursor(GLObject, true);
}
// check if boundary overlaps
if (mySelectionBoundary.overlapsWith(b)) {
return addElementUnderCursor(GLObject, false);
}
// check if the four boundary vertex are within circle
for (const auto &vertex : mySelectionBoundaryShape) {
if (vertex.distanceSquaredTo2D(center) <= squaredRadius) {
const Position &center, const double radius) {
// first check that object doesn't exist
if (isElementSelected(GLObject)) {
return false;
} else {
// declare squared radius
const double squaredRadius = (radius * radius);
// continue depending if we're selecting a position or a boundary
if (mySelectionBoundary.isInitialised()) {
// continue depending of detail level
if (d <= GUIVisualizationSettings::Detail::PreciseSelection) {
// make a boundary using center and radius
Boundary b;
b.add(center);
b.grow(radius);
// check if selection boundary contains the centering boundary of object
if (mySelectionBoundary.contains(GLObject->getCenteringBoundary())) {
return addElementUnderCursor(GLObject, true);
}
// check if boundary overlaps
if (mySelectionBoundary.overlapsWith(b)) {
return addElementUnderCursor(GLObject, false);
}
// check if the four boundary vertex are within circle
for (const auto &vertex : mySelectionBoundaryShape) {
if (vertex.distanceSquaredTo2D(center) <= squaredRadius) {
return addElementUnderCursor(GLObject, false);
}
}
// no intersection, then return false
return false;
} else {
// check if center is within mySelectionBoundary
if (mySelectionBoundary.around(center)) {
return addElementUnderCursor(GLObject, false);
} else {
return false;
}
}
// no intersection, then return false
return false;
} else {
// check if center is within mySelectionBoundary
if (mySelectionBoundary.around(center)) {
} else if (mySelectionPosition != Position::INVALID) {
// check distance between selection position and center
if (mySelectionPosition.distanceSquaredTo2D(center) <= squaredRadius) {
return addElementUnderCursor(GLObject, false);
} else {
return false;
}
}
} else if (mySelectionPosition != Position::INVALID) {
// check distance between selection position and center
if (mySelectionPosition.distanceSquaredTo2D(center) <= squaredRadius) {
return addElementUnderCursor(GLObject, false);
} else {
return false;
}
} else {
return false;
}
}

Expand Down Expand Up @@ -177,7 +199,8 @@ GUIViewObjectsHandler::checkGeometryPoint(const GUIVisualizationSettings::Detail

bool
GUIViewObjectsHandler::checkPositionOverShape(const GUIVisualizationSettings::Detail d, const GUIGlObject* GLObject,
const PositionVector &shape, const double distance) {
const PositionVector &shape, const double distance) {
// only process if we're selecting a precise position
if ((mySelectionPosition != Position::INVALID) && (d <= GUIVisualizationSettings::Detail::PreciseSelection)) {
// obtain nearest position over shape
const auto nearestPos = shape.positionAtOffset2D(shape.nearest_offset_to_point2D(mySelectionPosition));
Expand All @@ -196,8 +219,10 @@ GUIViewObjectsHandler::checkPositionOverShape(const GUIVisualizationSettings::De
bool
GUIViewObjectsHandler::checkShapeElement(const GUIVisualizationSettings::Detail d, const GUIGlObject* GLObject,
const PositionVector &shape) {
// continue depending if we're selecting a position or a boundary
if (mySelectionBoundary.isInitialised()) {
// first check that object doesn't exist
if (isElementSelected(GLObject)) {
return false;
}else if (mySelectionBoundary.isInitialised()) {
// check if selection boundary contains the centering boundary of object
if (mySelectionBoundary.contains(GLObject->getCenteringBoundary())) {
return addElementUnderCursor(GLObject, true);
Expand Down Expand Up @@ -225,14 +250,14 @@ GUIViewObjectsHandler::checkShapeElement(const GUIVisualizationSettings::Detail

const GUIViewObjectsHandler::GLObjectsSortedContainer&
GUIViewObjectsHandler::getSelectedObjects() const {
return myElementsUnderCursor;
return mySortedSelectedObjects;
}


const std::vector<int>&
GUIViewObjectsHandler::getGeometryPoints(const GUIGlObject* GLObject) const {
// avoid to insert duplicated elements
for (auto &elementLayer : myElementsUnderCursor) {
for (auto &elementLayer : mySortedSelectedObjects) {
for (auto &element : elementLayer.second) {
if (element.object == GLObject) {
return element.geometryPoints;
Expand All @@ -246,7 +271,7 @@ GUIViewObjectsHandler::getGeometryPoints(const GUIGlObject* GLObject) const {
const Position&
GUIViewObjectsHandler::getPositionOverShape(const GUIGlObject* GLObject) const {
// avoid to insert duplicated elements
for (auto &elementLayer : myElementsUnderCursor) {
for (auto &elementLayer : mySortedSelectedObjects) {
for (auto &element : elementLayer.second) {
if (element.object == GLObject) {
return element.posOverShape;
Expand All @@ -261,7 +286,7 @@ void
GUIViewObjectsHandler::updateFrontElement(const GUIGlObject* GLObject) {
ObjectContainer frontElement(nullptr);
// extract element
for (auto &elementLayer : myElementsUnderCursor) {
for (auto &elementLayer : mySortedSelectedObjects) {
auto it = elementLayer.second.begin();
while (it != elementLayer.second.end()) {
if (it->object == GLObject) {
Expand All @@ -277,27 +302,27 @@ GUIViewObjectsHandler::updateFrontElement(const GUIGlObject* GLObject) {
}
// add element again wit a new layer
if (frontElement.object) {
myElementsUnderCursor[(double)GLO_FRONTELEMENT].push_back(frontElement);
mySortedSelectedObjects[(double)GLO_FRONTELEMENT].push_back(frontElement);
}
}


bool
GUIViewObjectsHandler::addElementUnderCursor(const GUIGlObject* GLObject, const bool fullBoundary) {
// avoid to insert duplicated elements
// first check that object doesn't exist
if (isElementSelected(GLObject)) {
return false;
} else {
// check if this is an element with an associated layer
const auto layer = dynamic_cast<const Shape*>(GLObject);
if (layer) {
auto &layerContainer = myElementsUnderCursor[layer->getShapeLayer() * -1];
auto &layerContainer = mySortedSelectedObjects[layer->getShapeLayer() * -1];
layerContainer.insert(layerContainer.begin(), ObjectContainer(GLObject));
} else {
auto &layerContainer = myElementsUnderCursor[GLObject->getType() * -1];
auto &layerContainer = mySortedSelectedObjects[GLObject->getType() * -1];
layerContainer.insert(layerContainer.begin(), ObjectContainer(GLObject));
}
mySelectedObjets[GLObject] = fullBoundary;
mySelectedObjects[GLObject] = fullBoundary;
return true;
}
}
Expand All @@ -306,7 +331,7 @@ GUIViewObjectsHandler::addElementUnderCursor(const GUIGlObject* GLObject, const
bool
GUIViewObjectsHandler::addGeometryPointUnderCursor(const GUIGlObject* GLObject, const int newIndex) {
// avoid to insert duplicated elements
for (auto &elementLayer : myElementsUnderCursor) {
for (auto &elementLayer : mySortedSelectedObjects) {
for (auto &element : elementLayer.second) {
if (element.object == GLObject) {
// avoid double points
Expand All @@ -324,23 +349,23 @@ GUIViewObjectsHandler::addGeometryPointUnderCursor(const GUIGlObject* GLObject,
// no element found then add it
const auto layer = dynamic_cast<const Shape*>(GLObject);
if (layer) {
auto &layerContainer = myElementsUnderCursor[layer->getShapeLayer() * -1];
auto &layerContainer = mySortedSelectedObjects[layer->getShapeLayer() * -1];
auto it = layerContainer.insert(layerContainer.begin(), ObjectContainer(GLObject));
it->geometryPoints.push_back(newIndex);
} else {
auto &layerContainer = myElementsUnderCursor[GLObject->getType() * -1];
auto &layerContainer = mySortedSelectedObjects[GLObject->getType() * -1];
auto it = layerContainer.insert(layerContainer.begin(), ObjectContainer(GLObject));
it->geometryPoints.push_back(newIndex);
}
mySelectedObjets[GLObject] = false;
mySelectedObjects[GLObject] = false;
return true;
}


bool
GUIViewObjectsHandler::addPositionOverShape(const GUIGlObject* GLObject, const Position &pos) {
// avoid to insert duplicated elements
for (auto &elementLayer : myElementsUnderCursor) {
for (auto &elementLayer : mySortedSelectedObjects) {
for (auto &element : elementLayer.second) {
if (element.object == GLObject) {
if (element.posOverShape != Position::INVALID) {
Expand All @@ -355,17 +380,16 @@ GUIViewObjectsHandler::addPositionOverShape(const GUIGlObject* GLObject, const P
// no element found then add it
const auto layer = dynamic_cast<const Shape*>(GLObject);
if (layer) {
auto &layerContainer = myElementsUnderCursor[layer->getShapeLayer() * -1];
auto &layerContainer = mySortedSelectedObjects[layer->getShapeLayer() * -1];
auto it = layerContainer.insert(layerContainer.begin(), ObjectContainer(GLObject));
it->posOverShape = pos;
} else {
auto &layerContainer = myElementsUnderCursor[GLObject->getType() * -1];
auto &layerContainer = mySortedSelectedObjects[GLObject->getType() * -1];
auto it = layerContainer.insert(layerContainer.begin(), ObjectContainer(GLObject));
it->posOverShape = pos;
}
mySelectedObjets[GLObject] = false;
mySelectedObjects[GLObject] = false;
return true;
}


/****************************************************************************/
13 changes: 8 additions & 5 deletions src/utils/gui/div/GUIViewObjectsHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ class GUIViewObjectsHandler {
/// @brief constructor
GUIViewObjectsHandler();

/// @brief clear elements
void clearElements();
/// @brief clear selected elements
void clearSelectedElements();

/// @brief set selection position (usually the mouse position)
void setSelectionPosition(const Position &pos);
Expand All @@ -74,6 +74,9 @@ class GUIViewObjectsHandler {
/// @brief check if element was already selected
bool isElementSelected(const GUIGlObject* GLObject) const;

/// @brief check boundary parent element
bool checkBoundaryParentElement(const GUIGlObject* GLObject, const GUIGlObject* parent);

/// @brief check if mouse is within elements geometry (for circles)
bool checkCircleElement(const GUIVisualizationSettings::Detail d, const GUIGlObject* GLObject,
const Position &center, const double radius);
Expand Down Expand Up @@ -124,11 +127,11 @@ class GUIViewObjectsHandler {
const GUIGlObject* markedSecondGeometryPoint = nullptr;

protected:
/// @brief elements under cursor and their geometry point indexes sorted from top to bot
GLObjectsSortedContainer myElementsUnderCursor;
/// @brief selected element sorted by layer
GLObjectsSortedContainer mySortedSelectedObjects;

/// @brief map with selected elements and if was selected with full boundary (used only to avoid double seletions)
std::map<const GUIGlObject*, bool> mySelectedObjets;
std::map<const GUIGlObject*, bool> mySelectedObjects;

/// @brief add element into list of elements under cursor
bool addElementUnderCursor(const GUIGlObject* GLObject, const bool fullBoundary);
Expand Down

0 comments on commit 8a03a7f

Please sign in to comment.