#include <netedit/GNENet.h>
#include <netedit/GNEViewNet.h>
#include <utils/geom/GeomHelper.h>
#include <utils/gui/div/GLHelper.h>
#include <utils/gui/globjects/GLIncludes.h>
#include <utils/gui/globjects/GUIGlObjectTypes.h>
#include <utils/options/OptionsCont.h>
#include <utils/gui/div/GUIGlobalViewObjectsHandler.h>
#include "GNEContour.h"
#include "GNEAttributeCarrier.h"
GUIDottedGeometry::DottedGeometryColor GNEContour::myDottedGeometryColor;
GNEContour::GNEContour() :
myDottedGeometries(new std::vector<GUIDottedGeometry>(4)),
myContourBoundary(new Boundary),
myCalculatedShape(new PositionVector) {
}
GNEContour::~GNEContour() {
delete myDottedGeometries;
delete myContourBoundary;
delete myCalculatedShape;
}
Boundary
GNEContour::getContourBoundary() const {
return *myContourBoundary;
}
void
GNEContour::clearContour() const {
for (int i = 0; i < 3; i++) {
myDottedGeometries->at(i).clearDottedGeometry();
}
myContourBoundary->reset();
myCalculatedShape->clear();
}
void
GNEContour::calculateContourClosedShape(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GUIGlObject* glObject, const PositionVector& shape, const double layer,
const double scale, const GUIGlObject* boundaryParent, const bool addToSelectedObjects) const {
if (s.drawForViewObjectsHandler && !gViewObjectsHandler.checkRectangleSelection(s, glObject, layer, boundaryParent)) {
buildContourClosedShape(s, d, shape, scale);
if (addToSelectedObjects) {
gViewObjectsHandler.checkShapeObject(glObject, *myCalculatedShape, *myContourBoundary, layer, nullptr);
}
}
}
void
GNEContour::calculateContourExtrudedShape(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GUIGlObject* glObject, const PositionVector& shape, const double layer, const double extrusionWidth,
const double scale, const bool closeFirstExtrem, const bool closeLastExtrem, const double offset,
const GNESegment* segment, const GUIGlObject* boundaryParent, const bool addToSelectedObjects) const {
if (s.drawForViewObjectsHandler && !gViewObjectsHandler.checkRectangleSelection(s, glObject, layer, boundaryParent)) {
buildContourExtrudedShape(s, d, shape, extrusionWidth, scale, closeFirstExtrem, closeLastExtrem, offset);
if (addToSelectedObjects) {
gViewObjectsHandler.checkShapeObject(glObject, *myCalculatedShape, *myContourBoundary, layer, segment);
}
}
}
void
GNEContour::calculateContourRectangleShape(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GUIGlObject* glObject, const Position& pos, const double width, const double height, const double layer,
const double offsetX, const double offsetY, const double rot, const double scale, const GUIGlObject* boundaryParent) const {
if (s.drawForViewObjectsHandler && !gViewObjectsHandler.checkRectangleSelection(s, glObject, layer, boundaryParent)) {
buildContourRectangle(s, d, pos, width, height, offsetX, offsetY, rot, scale);
gViewObjectsHandler.checkShapeObject(glObject, *myCalculatedShape, *myContourBoundary, layer, nullptr);
}
}
void
GNEContour::calculateContourCircleShape(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GUIGlObject* glObject, const Position& pos, double radius, const double layer,
const double scale, const GUIGlObject* boundaryParent) const {
if (s.drawForViewObjectsHandler && !gViewObjectsHandler.checkRectangleSelection(s, glObject, layer, boundaryParent)) {
buildContourCircle(s, d, pos, radius, scale);
gViewObjectsHandler.checkCircleObject(d, glObject, pos, (radius * scale), layer);
}
}
void
GNEContour::calculateContourEdge(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GNEEdge* edge, const GUIGlObject* elementToRegister, const double layer,
const bool closeFirstExtrem, const bool closeLastExtrem) const {
if (s.drawForViewObjectsHandler) {
buildContourEdge(s, d, edge, closeFirstExtrem, closeLastExtrem);
gViewObjectsHandler.checkShapeObject(elementToRegister, *myCalculatedShape, *myContourBoundary, layer, nullptr);
}
}
void
GNEContour::calculateContourEdges(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GNEEdge* fromEdge, const GNEEdge* toEdge) const {
buildContourEdges(s, d, fromEdge, toEdge);
}
void
GNEContour::calculateContourFirstGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GUIGlObject* glObject, const PositionVector& shape, const double layer, double radius, const double scale) const {
if (s.drawForViewObjectsHandler && (shape.size() > 0)) {
gViewObjectsHandler.checkGeometryPoint(d, glObject, shape, 0, layer, (radius * scale));
}
}
void
GNEContour::calculateContourLastGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GUIGlObject* glObject, const PositionVector& shape, const double layer, double radius, const double scale) const {
if (s.drawForViewObjectsHandler && (shape.size() > 0)) {
gViewObjectsHandler.checkGeometryPoint(d, glObject, shape, (int)shape.size() - 1, layer, (radius * scale));
}
}
void
GNEContour::calculateContourMiddleGeometryPoints(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GUIGlObject* glObject, const PositionVector& shape, const double layer, double radius, const double scale) const {
if (s.drawForViewObjectsHandler) {
for (int i = 1; i < (int)shape.size() - 1; i++) {
gViewObjectsHandler.checkGeometryPoint(d, glObject, shape, i, layer, (radius * scale));
}
gViewObjectsHandler.checkPositionOverShape(d, glObject, shape, layer, (radius * scale));
}
}
void
GNEContour::calculateContourAllGeometryPoints(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GUIGlObject* glObject, const PositionVector& shape, const double layer, double radius, const double scale,
const bool calculatePosOverShape) const {
if (s.drawForViewObjectsHandler) {
for (int i = 0; i < (int)shape.size(); i++) {
gViewObjectsHandler.checkGeometryPoint(d, glObject, shape, i, layer, (radius * scale));
}
if (calculatePosOverShape) {
gViewObjectsHandler.checkPositionOverShape(d, glObject, shape, layer, (radius * scale));
}
}
}
void
GNEContour::calculateContourEdgeGeometryPoints(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GNEEdge* edge, const double radius, const bool calculatePosOverShape, const bool firstExtrem, const bool lastExtrem) const {
if (s.drawForViewObjectsHandler && (gViewObjectsHandler.getSelectionPosition() != Position::INVALID)) {
const auto& edgeGeometry = edge->getNBEdge()->getGeometry();
const int lastGeometryPointIndex = (int)edgeGeometry.size() - 1;
if (myCalculatedShape->around(gViewObjectsHandler.getSelectionPosition())) {
const auto squaredRadius = (radius * radius);
const auto nearestOffset = edgeGeometry.nearest_offset_to_point2D(gViewObjectsHandler.getSelectionPosition());
const auto nearestPos = edgeGeometry.positionAtOffset2D(nearestOffset);
for (int i = 1; i < lastGeometryPointIndex; i++) {
if (edgeGeometry[i].distanceSquaredTo2D(nearestPos) <= squaredRadius) {
gViewObjectsHandler.checkGeometryPoint(d, edge, edgeGeometry, i, edge->getType(), radius);
}
}
if (firstExtrem) {
if (edgeGeometry[0].distanceSquaredTo2D(nearestPos) <= squaredRadius) {
gViewObjectsHandler.checkGeometryPoint(d, edge, edgeGeometry, 0, edge->getType(), radius);
}
}
if (lastExtrem) {
if (edgeGeometry[lastGeometryPointIndex].distanceSquaredTo2D(nearestPos) <= squaredRadius) {
gViewObjectsHandler.checkGeometryPoint(d, edge, edgeGeometry, lastGeometryPointIndex, edge->getType(), radius);
}
}
if (calculatePosOverShape && gViewObjectsHandler.getSelectedGeometryPoints(edge).empty()) {
gViewObjectsHandler.selectPositionOverShape(edge, nearestPos, edge->getType(), nearestOffset);
}
} else {
for (int i = 1; i < lastGeometryPointIndex; i++) {
gViewObjectsHandler.checkGeometryPoint(d, edge, edgeGeometry, i, edge->getType(), radius);
}
if (firstExtrem) {
gViewObjectsHandler.checkGeometryPoint(d, edge, edgeGeometry, 0, edge->getType(), radius);
}
if (lastExtrem) {
gViewObjectsHandler.checkGeometryPoint(d, edge, edgeGeometry, lastGeometryPointIndex, edge->getType(), radius);
}
}
}
}
bool
GNEContour::checkDrawPathContour(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GNEAttributeCarrier* AC) const {
if (s.drawForViewObjectsHandler && !s.disableDottedContours && (d <= GUIVisualizationSettings::Detail::DottedContours)) {
if (AC->checkDrawFromContour()) {
return true;
}
if (AC->checkDrawToContour()) {
return true;
}
if (AC->checkDrawRelatedContour()) {
return true;
}
if (AC->checkDrawOverContour()) {
return true;
}
if (AC->checkDrawInspectContour()) {
return true;
}
if (AC->checkDrawFrontContour()) {
return true;
}
if (AC->checkDrawDeleteContour()) {
return true;
}
if (AC->checkDrawDeleteContourSmall()) {
return true;
}
if (AC->checkDrawSelectContour()) {
return true;
}
if (AC->checkDrawMoveContour()) {
return true;
}
}
return false;
}
bool
GNEContour::drawDottedContours(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GNEAttributeCarrier* AC, const double lineWidth, const bool addOffset) const {
if (!s.disableDottedContours && (d <= GUIVisualizationSettings::Detail::DottedContours)) {
if (AC->checkDrawFromContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::FROM, lineWidth, addOffset);
}
if (AC->checkDrawToContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::TO, lineWidth, addOffset);
}
if (AC->checkDrawRelatedContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::RELATED, lineWidth, addOffset);
}
if (AC->checkDrawOverContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::OVER, lineWidth, addOffset);
}
if (AC->checkDrawInspectContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::INSPECT, lineWidth, addOffset);
}
if (AC->checkDrawFrontContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::FRONT, lineWidth, addOffset);
}
if (AC->checkDrawDeleteContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::REMOVE, lineWidth, addOffset);
} else if (AC->checkDrawDeleteContourSmall()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::REMOVE, s.dottedContourSettings.segmentWidthSmall, addOffset);
}
if (AC->checkDrawSelectContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::SELECT, lineWidth, addOffset);
}
if (AC->checkDrawMoveContour()) {
return drawDottedContour(s, GUIDottedGeometry::DottedContourType::MOVE, lineWidth, addOffset);
}
return false;
}
return false;
}
void
GNEContour::drawDottedContourGeometryPoints(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GNEAttributeCarrier* AC, const PositionVector& shape, const double radius,
const double scale, const double lineWidth) const {
if (!s.disableDottedContours && (d <= GUIVisualizationSettings::Detail::DottedContours) && AC->checkDrawMoveContour()) {
const auto glObject = AC->getGUIGlObject();
const auto& geometryPoints = gViewObjectsHandler.getSelectedGeometryPoints(glObject);
const auto& posOverShape = gViewObjectsHandler.getSelectedPositionOverShape(glObject);
if (geometryPoints.size() > 0) {
for (const auto& geometryPoint : geometryPoints) {
const auto circleShape = GUIGeometry::getVertexCircleAroundPosition(shape[geometryPoint], radius * scale, 16);
const auto dottedGeometry = GUIDottedGeometry(s, d, circleShape, true);
myDottedGeometryColor.reset();
GLHelper::pushMatrix();
glTranslated(0, 0, GLO_DOTTEDCONTOUR);
dottedGeometry.drawDottedGeometry(s, GUIDottedGeometry::DottedContourType::MOVE, myDottedGeometryColor, lineWidth, 0);
GLHelper::popMatrix();
}
} else if (posOverShape != Position::INVALID) {
const auto circleShape = GUIGeometry::getVertexCircleAroundPosition(posOverShape, radius * scale, 16);
const auto dottedGeometry = GUIDottedGeometry(s, d, circleShape, true);
myDottedGeometryColor.reset();
GLHelper::pushMatrix();
glTranslated(0, 0, GLO_DOTTEDCONTOUR);
dottedGeometry.drawDottedGeometry(s, GUIDottedGeometry::DottedContourType::MOVE, myDottedGeometryColor, lineWidth, 0);
GLHelper::popMatrix();
}
}
}
void
GNEContour::drawInnenContourClosed(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const PositionVector& shape, const double scale, const double lineWidth) const {
*myCalculatedShape = shape;
if ((myCalculatedShape->size() > 2) && (scale > 0)) {
myCalculatedShape->scaleRelative(scale);
myCalculatedShape->closePolygon();
myDottedGeometries->at(0) = GUIDottedGeometry(s, d, *myCalculatedShape, true);
myDottedGeometryColor.reset();
GLHelper::pushMatrix();
myDottedGeometries->at(0).drawInnenGeometry(lineWidth);
GLHelper::popMatrix();
}
}
bool
GNEContour::drawDottedContour(const GUIVisualizationSettings& s, GUIDottedGeometry::DottedContourType type,
const double lineWidth, const bool addOffset) const {
myDottedGeometryColor.reset();
GLHelper::pushMatrix();
glTranslated(0, 0, GLO_DOTTEDCONTOUR);
for (const auto& dottedGeometry : *myDottedGeometries) {
dottedGeometry.drawDottedGeometry(s, type, myDottedGeometryColor, lineWidth, addOffset);
}
GLHelper::popMatrix();
return true;
}
void
GNEContour::buildContourClosedShape(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const PositionVector& shape, const double scale) const {
*myCalculatedShape = shape;
if ((myCalculatedShape->size() > 2) && (scale > 0)) {
myCalculatedShape->scaleRelative(scale);
myCalculatedShape->closePolygon();
myDottedGeometries->at(0) = GUIDottedGeometry(s, d, *myCalculatedShape, true);
*myContourBoundary = myCalculatedShape->getBoxBoundary();
} else {
myContourBoundary->reset();
}
}
void
GNEContour::buildContourExtrudedShape(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const PositionVector& shape, const double extrusionWidth, const double scale,
const bool closeFirstExtrem, const bool closeLastExtrem, const double offset) const {
myCalculatedShape->clear();
if (shape.size() > 1 && (extrusionWidth > 0)) {
myDottedGeometries->at(0) = GUIDottedGeometry(s, d, shape, false);
myDottedGeometries->at(2) = GUIDottedGeometry(s, d, shape.reverse(), false);
myDottedGeometries->at(0).moveShapeToSide((extrusionWidth * scale * -1) + offset);
myDottedGeometries->at(2).moveShapeToSide((extrusionWidth * scale * -1) - offset);
if (closeFirstExtrem) {
myDottedGeometries->at(3) = GUIDottedGeometry(s, d, {
myDottedGeometries->at(2).getBackPosition(),
myDottedGeometries->at(0).getFrontPosition()
}, false);
}
if (closeLastExtrem) {
myDottedGeometries->at(1) = GUIDottedGeometry(s, d, {
myDottedGeometries->at(0).getBackPosition(),
myDottedGeometries->at(2).getFrontPosition()
}, false);
}
for (const auto& position : myDottedGeometries->at(0).getUnresampledShape()) {
myCalculatedShape->push_back(position);
}
for (const auto& position : myDottedGeometries->at(2).getUnresampledShape()) {
myCalculatedShape->push_back(position);
}
*myContourBoundary = myCalculatedShape->getBoxBoundary();
} else {
myContourBoundary->reset();
}
}
void
GNEContour::buildContourRectangle(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const Position& pos, const double width, const double height, const double offsetX,
const double offsetY, const double rot, const double scale) const {
myCalculatedShape->clear();
if (((width + height) > 0) && (scale > 0)) {
myCalculatedShape->push_back(Position(0 + width, 0 + height));
myCalculatedShape->push_back(Position(0 + width, 0 - height));
myCalculatedShape->push_back(Position(0 - width, 0 - height));
myCalculatedShape->push_back(Position(0 - width, 0 + height));
myCalculatedShape->add(offsetX, offsetY, 0);
myCalculatedShape->scaleRelative(scale);
myCalculatedShape->rotate2D(DEG2RAD((rot * -1) + 90));
myCalculatedShape->add(pos);
myDottedGeometries->at(0) = GUIDottedGeometry(s, d, *myCalculatedShape, true);
*myContourBoundary = myCalculatedShape->getBoxBoundary();
} else {
myContourBoundary->reset();
}
}
void
GNEContour::buildContourCircle(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const Position& pos, double radius, const double scale) const {
myCalculatedShape->clear();
const double scaledRadius = radius * scale;
if (scaledRadius > POSITION_EPS) {
if (d <= GUIVisualizationSettings::Detail::CircleResolution32) {
*myCalculatedShape = GUIGeometry::getVertexCircleAroundPosition(pos, scaledRadius, 16);
} else if (d <= GUIVisualizationSettings::Detail::CircleResolution16) {
*myCalculatedShape = GUIGeometry::getVertexCircleAroundPosition(pos, scaledRadius, 8);
} else {
myCalculatedShape->push_back(Position(pos.x() - radius, pos.y() - radius));
myCalculatedShape->push_back(Position(pos.x() - radius, pos.y() + radius));
myCalculatedShape->push_back(Position(pos.x() + radius, pos.y() + radius));
myCalculatedShape->push_back(Position(pos.x() + radius, pos.y() - radius));
}
myDottedGeometries->at(0) = GUIDottedGeometry(s, d, *myCalculatedShape, true);
*myContourBoundary = myCalculatedShape->getBoxBoundary();
} else {
myContourBoundary->reset();
}
}
void
GNEContour::buildContourEdge(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
const GNEEdge* edge, const bool closeFirstExtrem, const bool closeLastExtrem) const {
myCalculatedShape->clear();
const bool lefthand = OptionsCont::getOptions().getBool("lefthand");
const GNELane* topLane = lefthand ? edge->getChildLanes().front() : edge->getChildLanes().back();
const GNELane* botLane = lefthand ? edge->getChildLanes().back() : edge->getChildLanes().front();
myDottedGeometries->at(0) = GUIDottedGeometry(s, d, topLane->getLaneGeometry().getShape(), false);
myDottedGeometries->at(2) = GUIDottedGeometry(s, d, botLane->getLaneGeometry().getShape().reverse(), false);
myDottedGeometries->at(0).moveShapeToSide((topLane->getDrawingConstants()->getDrawingWidth() * -1) + topLane->getDrawingConstants()->getOffset());
myDottedGeometries->at(2).moveShapeToSide((botLane->getDrawingConstants()->getDrawingWidth() * -1) - botLane->getDrawingConstants()->getOffset());
if (closeFirstExtrem) {
myDottedGeometries->at(3) = GUIDottedGeometry(s, d, {
myDottedGeometries->at(2).getBackPosition(),
myDottedGeometries->at(0).getFrontPosition()
}, false);
}
if (closeLastExtrem) {
myDottedGeometries->at(1) = GUIDottedGeometry(s, d, {
myDottedGeometries->at(0).getBackPosition(),
myDottedGeometries->at(2).getFrontPosition()
}, false);
}
for (const auto& position : myDottedGeometries->at(0).getUnresampledShape()) {
myCalculatedShape->push_back(position);
}
for (const auto& position : myDottedGeometries->at(2).getUnresampledShape()) {
myCalculatedShape->push_back(position);
}
*myContourBoundary = myCalculatedShape->getBoxBoundary();
}
void
GNEContour::buildContourEdges(const GUIVisualizationSettings& , const GUIVisualizationSettings::Detail ,
const GNEEdge* , const GNEEdge* ) const {
}