/**************************************************************************** Copyright (C) 2010-2012 the Office National des ForĂȘts (ONF), France All rights reserved. Contact : alexandre.piboule@onf.fr Developers : Alexandre PIBOULE (ONF) This file is part of PluginONF library. PluginONF is free library: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. PluginONF is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with PluginONF. If not, see . *****************************************************************************/ #include "actions/onf_actionselectsceneforeachposition.h" #include "ct_global/ct_context.h" #include "ct_iterator/ct_pointiterator.h" #include "ct_color.h" #include "ct_math/ct_mathpoint.h" #include "ct_pointcloudindex/ct_pointcloudindexvector.h" #include "ct_itemdrawable/ct_scene.h" #include #include #include #include #include #include #include #include "math.h" ONF_ActionSelectSceneForEachPosition_dataContainer::ONF_ActionSelectSceneForEachPosition_dataContainer() { } ONF_ActionSelectSceneForEachPosition::ONF_ActionSelectSceneForEachPosition(ONF_ActionSelectSceneForEachPosition_dataContainer *dataContainer) : CT_AbstractActionForGraphicsView() { _dataContainer = dataContainer; _selectedPos = NULL; _previousSelectedPos = NULL; _selectOption = NULL; _selectTool = NULL; _currentScene = NULL; _automaticColorList.append(QColor(255, 0, 255)); // Rose _automaticColorList.append(QColor(255,200,255)); // Magenta Clair _automaticColorList.append(QColor(200,255,255)); // Cyan Clair _automaticColorList.append(QColor(200,200,255)); // Mauve Clair _automaticColorList.append(QColor(255,200,150)); // Orange clair _automaticColorList.append(QColor(150,200,255)); // Bleu Clair _automaticColorList.append(QColor(200,255,150)); // Vert-Jaune Clair _automaticColorList.append(QColor(200,150,255)); // Violet Clair _automaticColorList.append(QColor(0 ,0 ,255)); // Bleu _automaticColorList.append(QColor(255,150,0 )); // Orange _automaticColorList.append(QColor(0 ,255,150)); // Turquoise _automaticColorList.append(QColor(150,0 ,255)); // Violet _unmatchedColor = QColor(125,125,125); // Grey _cylinderColor1 = QColor(0, 255, 255); _cylinderColor2 = QColor(0, 100, 255); _highlightedCylindersColor1 = QColor(0, 255, 0); _highlightedCylindersColor2 = QColor(0, 100, 0); _selectedCylinderColor1 = QColor(255,255,0 ); _selectedCylinderColor2 = QColor(255,255,200); _segmentMode = false; } ONF_ActionSelectSceneForEachPosition::~ONF_ActionSelectSceneForEachPosition() { document()->removeAllItemDrawable(); if (_selectOption != NULL) { ONF_ActionSelectSceneForEachPositionOptions *option = (ONF_ActionSelectSceneForEachPositionOptions*)optionAt(0); if (option != NULL) { option->clearSelectionWidget(_selectOption); } delete _selectOption; } if (_selectTool != NULL) {delete _selectTool;} } QString ONF_ActionSelectSceneForEachPosition::uniqueName() const { return "ONF_ActionSelectSceneForEachPosition"; } QString ONF_ActionSelectSceneForEachPosition::title() const { return "Select scene for position"; } QString ONF_ActionSelectSceneForEachPosition::description() const { return "Select scene for position"; } QIcon ONF_ActionSelectSceneForEachPosition::icon() const { return QIcon(":/icons/select_rectangular.png"); } QString ONF_ActionSelectSceneForEachPosition::type() const { return CT_AbstractAction::TYPE_MODIFICATION; } void ONF_ActionSelectSceneForEachPosition::init() { CT_AbstractActionForGraphicsView::init(); if(nOptions() == 0) { // create the option widget if it was not already created ONF_ActionSelectSceneForEachPositionOptions *option = new ONF_ActionSelectSceneForEachPositionOptions(this); // add the options to the graphics view graphicsView()->addActionOptions(option); connect(option, SIGNAL(parametersChanged()), this, SLOT(redrawOverlayAnd3D())); connect(option, SIGNAL(updateColorization()), this, SLOT(updateColorization())); connect(option, SIGNAL(addCluster()), this, SLOT(addCluster())); connect(option, SIGNAL(removeCluster()), this, SLOT(removeCluster())); connect(option, SIGNAL(switchCluster()), this, SLOT(switchCluster())); connect(option, SIGNAL(initColors()), this, SLOT(initColors())); connect(option, SIGNAL(beginSegmentCluster()), this, SLOT(initSegmentMode())); connect(option, SIGNAL(endSegmentCluster()), this, SLOT(validateSegmentMode())); connect(option, SIGNAL(hideNotSelectedToggled()), this, SLOT(hideNotSelectedToggled())); // register the option to the superclass, so the hideOptions and showOptions // is managed automatically registerOption(option); _selectTool = new CT_ActionSelectTool(); _selectOption = new CT_ActionSelectItemDrawableGVOptions(NULL, _selectTool); _selectOption->setAvailableModes(false, true, false, false); _selectOption->setAvailableSelectionModes(true, true, true, true, true, true); _selectTool->init(graphicsView(), _selectOption); connect(_selectTool, SIGNAL(selectionModeChanged(GraphicsViewInterface::SelectionMode)), _selectOption, SLOT(setSelectionMode(GraphicsViewInterface::SelectionMode))); connect(_selectTool, SIGNAL(needRedrawOverlay()), this, SLOT(redrawOverlay())); option->setSelectionWidget(_selectOption); document()->removeAllItemDrawable(); GraphicsViewInterface* view = dynamic_cast(document()->views().first()); view->setSelectionMode(GraphicsViewInterface::SELECT_ONE); for (int i = 0 ; i < _dataContainer->_scenes.size() ; i++) { CT_AbstractItemDrawableWithPointCloud* scene = (CT_AbstractItemDrawableWithPointCloud*) _dataContainer->_scenes.at(i); document()->addItemDrawable(*scene); } _colorNum = 0; _sceneColors.resize(_dataContainer->_scenes.size()); initColors(); document()->redrawGraphics(DocumentInterface::RO_WaitForConversionCompleted); view->camera()->fitCameraToVisibleItems(); view->camera()->setOrientation(0.2, 0, 0, 0.95); } } void ONF_ActionSelectSceneForEachPosition::initColors() { for (int i = 0 ; i < _dataContainer->_scenes.size() ; i++) { _sceneColors[i] = _automaticColorList.at(std::rand() % _automaticColorList.size()); } // _colorNum = std::rand() % _automaticColorList.size(); // for (int i = 0 ; i < _dataContainer->_scenes.size() ; i++) // { // if (_dataContainer->_matched[i]) // { // _sceneColors[i] = nextColor(); // } // } // for (int i = 0 ; i < _dataContainer->_scenes.size() ; i++) // { // if (!_dataContainer->_matched[i]) // { // _sceneColors[i] = nextColor(); // } // } updateColorization(); } void ONF_ActionSelectSceneForEachPosition::initSegmentMode() { if (document()->getSelectedItemDrawable().size() == 1) { _segmentMode = true; _selectOption->setSelectionMode(GraphicsViewInterface::SELECT_ONE_POINT); graphicsView()->setSelectionMode(GraphicsViewInterface::SELECT_ONE_POINT); _currentScene = (CT_AbstractItemDrawableWithPointCloud*) document()->getSelectedItemDrawable().first(); document()->setSelectAllItemDrawable(false); document()->removeAllItemDrawable(); document()->addItemDrawable(*_currentScene); GraphicsViewInterface* view = dynamic_cast(document()->views().first()); view->camera()->setCX(_currentScene->getCenterX()); view->camera()->setCY(_currentScene->getCenterY()); view->camera()->setCZ(_currentScene->getCenterZ()); redrawOverlayAnd3D(); } else { ONF_ActionSelectSceneForEachPositionOptions *option = (ONF_ActionSelectSceneForEachPositionOptions*)optionAt(0); option->setSegmentMode(false); } } void ONF_ActionSelectSceneForEachPosition::updatePositionApex(ONF_ActionSelectSceneForEachPosition_treePosition* treePos) { treePos->_apex = Eigen::Vector3d(0,0, -std::numeric_limits::max()); treePos->_hasApex = false; for (int i = 0 ; i < treePos->_scenesIds.size() ; i++) { int index = treePos->_scenesIds.at(i); const Eigen::Vector3d& apex = _dataContainer->_scenesApex.at(index); if (apex(2) > treePos->_apex(2)) { treePos->_apex = apex; treePos->_hasApex = true; } } } void ONF_ActionSelectSceneForEachPosition::validateSegmentMode() { if (_segmentMode) { _segmentMode = false; qDebug() << "_currentScene->getPointCloudIndexSize()=" << _currentScene->getPointCloudIndexSize(); // Selected points CT_CIR pcir1 = graphicsView()->getSelectedPoints(); CT_PointIterator it1(pcir1); if (it1.size() > 0 && it1.size() < _currentScene->getPointCloudIndexSize()) { CT_PointCloudIndexVector *cloud1 = new CT_PointCloudIndexVector(); cloud1->setSortType(CT_PointCloudIndexVector::NotSorted); Eigen::Vector3d apex1; apex1(2) = -std::numeric_limits::max(); while (it1.hasNext()) { it1.next(); size_t index1 = it1.currentGlobalIndex(); Eigen::Vector3d coord1 = it1.currentPoint(); cloud1->addIndex(index1); if (coord1(2) > apex1(2)) {apex1 = coord1;} } cloud1->setSortType(CT_PointCloudIndexVector::SortedInAscendingOrder); qDebug() << "cloud1->size()=" << cloud1->size(); // Not selected points CT_PointCloudIndexVector *cloud2 = new CT_PointCloudIndexVector(); cloud2->setSortType(CT_PointCloudIndexVector::NotSorted); Eigen::Vector3d apex2; apex2(2) = -std::numeric_limits::max(); graphicsView()->togglePointsSelected(); CT_CIR pcir2 = graphicsView()->getSelectedPoints(); CT_PointIterator it2(pcir2); while (it2.hasNext()) { it2.next(); size_t index2 = it2.currentGlobalIndex(); Eigen::Vector3d coord2 = it2.currentPoint(); cloud2->addIndex(index2); if (coord2(2) > apex2(2)) {apex2 = coord2;} } cloud2->setSortType(CT_PointCloudIndexVector::SortedInAscendingOrder); qDebug() << "cloud2->size()=" << cloud2->size(); CT_Scene *scene1 = new CT_Scene("ONF_ActionSelectSceneForEachPosition001", _currentScene->result(), PS_REPOSITORY->registerPointCloudIndex(cloud1)); scene1->updateBoundingBox(); CT_Scene *scene2 = new CT_Scene("ONF_ActionSelectSceneForEachPosition001", _currentScene->result(), PS_REPOSITORY->registerPointCloudIndex(cloud2)); scene2->updateBoundingBox(); int currentSceneIndex = _dataContainer->_scenes.indexOf(_currentScene); _dataContainer->_scenes.replace(currentSceneIndex, scene1); _dataContainer->_scenes.append(scene2); _dataContainer->_scenesApex.replace(currentSceneIndex, apex1); _dataContainer->_scenesApex.append(apex2); _dataContainer->_matched.push_back(false); _dataContainer->_toDelete.append(scene1); _dataContainer->_toDelete.append(scene2); _sceneColors.push_back(nextColor()); for (int i = 0 ; i < _dataContainer->_positions.size() ; i++) { ONF_ActionSelectSceneForEachPosition_treePosition* treePos = _dataContainer->_positions.at(i); if (treePos->_scenesIds.contains(currentSceneIndex)) { updatePositionApex(treePos); } } updateColorization(); } document()->setSelectAllItemDrawable(false); document()->removeAllItemDrawable(); _selectOption->setSelectionMode(GraphicsViewInterface::SELECT_ONE); graphicsView()->setSelectionMode(GraphicsViewInterface::SELECT_ONE); for (int i = 0 ; i < _dataContainer->_scenes.size() ; i++) { CT_AbstractItemDrawableWithPointCloud* scene = (CT_AbstractItemDrawableWithPointCloud*) _dataContainer->_scenes.at(i); document()->addItemDrawable(*scene); } redrawOverlayAnd3D(); } } void ONF_ActionSelectSceneForEachPosition::hideNotSelectedToggled() { ONF_ActionSelectSceneForEachPositionOptions *option = (ONF_ActionSelectSceneForEachPositionOptions*)optionAt(0); document()->removeAllItemDrawable(); if (option->hideNotSelected()) { document()->removeAllItemDrawable(); if (_selectedPos != NULL) { for (int i = 0 ; i < _selectedPos->_scenesIds.size() ; i++) { CT_AbstractItemDrawableWithPointCloud* scene = (CT_AbstractItemDrawableWithPointCloud*) _dataContainer->_scenes.at(_selectedPos->_scenesIds.at(i)); document()->addItemDrawable(*scene); } double visibleDist = option->visibleDist(); if (visibleDist > 0) { for (int i = 0 ; i < _dataContainer->_scenes.size() ; i++) { CT_AbstractItemDrawableWithPointCloud* scene = (CT_AbstractItemDrawableWithPointCloud*) _dataContainer->_scenes.at(i); double dist = sqrt(pow(_dataContainer->_scenesApex.at(i)(0) - _selectedPos->_base(0), 2) + pow(_dataContainer->_scenesApex.at(i)(1) - _selectedPos->_base(1), 2)); if (dist < visibleDist) { document()->addItemDrawable(*scene); } } } } } else { for (int i = 0 ; i < _dataContainer->_scenes.size() ; i++) { CT_AbstractItemDrawableWithPointCloud* scene = (CT_AbstractItemDrawableWithPointCloud*) _dataContainer->_scenes.at(i); document()->addItemDrawable(*scene); } } redrawOverlayAnd3D(); } QColor ONF_ActionSelectSceneForEachPosition::nextColor() { int num = _colorNum++; if (_colorNum >= _automaticColorList.size()) {_colorNum = 0;} return _automaticColorList.at(num); } void ONF_ActionSelectSceneForEachPosition::colorizeScenes() { ONF_ActionSelectSceneForEachPositionOptions *option = (ONF_ActionSelectSceneForEachPositionOptions*)optionAt(0); for (int i = 0 ; i < _dataContainer->_scenes.size() ; i++) { CT_AbstractItemDrawableWithPointCloud* scene = (CT_AbstractItemDrawableWithPointCloud*) _dataContainer->_scenes.at(i); if (_selectedPos != NULL && _selectedPos->_scenesIds.contains(i)) { document()->setColor(scene, _selectedCylinderColor1); } else if (_dataContainer->_matched[i] || option->colorUnmatched()) { document()->setColor(scene, _sceneColors[i]); } else { document()->setColor(scene, _unmatchedColor); } } } void ONF_ActionSelectSceneForEachPosition::addCluster() { QList items = document()->getSelectedItemDrawable(); if (items.size() > 0 && _selectedPos != NULL) { int index = _dataContainer->_scenes.indexOf(items.first()); if (!_selectedPos->_scenesIds.contains(index)) { for (int i = 0 ; i < _dataContainer->_positions.size() ; i++) { ONF_ActionSelectSceneForEachPosition_treePosition* treePos = _dataContainer->_positions.at(i); if (treePos != _selectedPos && treePos->_scenesIds.contains(index)) { treePos->_scenesIds.removeOne(index); if (treePos->_scenesIds.isEmpty()) { treePos->_apex = Eigen::Vector3d(0,0,0); treePos->_hasApex = false; } else { updatePositionApex(treePos); } } } _selectedPos->_scenesIds.append(index); const Eigen::Vector3d& apex = _dataContainer->_scenesApex.at(index); _sceneColors[index] = _sceneColors[_selectedPos->_scenesIds.first()]; _dataContainer->_matched[index] = true; if (apex(2) > _selectedPos->_apex(2)) { _selectedPos->_apex = apex; _selectedPos->_hasApex = true; } } } colorizeScenes(); redrawOverlayAnd3D(); } void ONF_ActionSelectSceneForEachPosition::removeCluster() { QList items = document()->getSelectedItemDrawable(); if (items.size() > 0 && _selectedPos != NULL) { int index = _dataContainer->_scenes.indexOf(items.first()); if (_selectedPos->_scenesIds.contains(index)) { _selectedPos->_scenesIds.removeOne(index); _sceneColors[index] = nextColor(); _dataContainer->_matched[index] = false; if (_selectedPos->_scenesIds.isEmpty()) { _selectedPos->_apex = Eigen::Vector3d(0,0,0); _selectedPos->_hasApex = false; } else { updatePositionApex(_selectedPos); } } } colorizeScenes(); redrawOverlayAnd3D(); } void ONF_ActionSelectSceneForEachPosition::switchCluster() { QList items = document()->getSelectedItemDrawable(); if (items.size() > 0 && _selectedPos != NULL) { int index = _dataContainer->_scenes.indexOf(items.first()); for (int i = 0 ; i < _dataContainer->_positions.size() ; i++) { ONF_ActionSelectSceneForEachPosition_treePosition* treePos = _dataContainer->_positions.at(i); if (treePos != _selectedPos && treePos->_scenesIds.contains(index)) { treePos->_scenesIds.removeOne(index); if (treePos->_scenesIds.isEmpty()) { treePos->_apex = Eigen::Vector3d(0,0,0); treePos->_hasApex = false; } else { updatePositionApex(treePos); } } } for (int i = 0 ; i < _selectedPos->_scenesIds.size() ; i++) { int sceneId = _selectedPos->_scenesIds.at(i); _dataContainer->_matched[sceneId] = false; _sceneColors[sceneId] = nextColor(); } _selectedPos->_scenesIds.clear(); _selectedPos->_scenesIds.append(index); _dataContainer->_matched[index] = true; const Eigen::Vector3d& apex = _dataContainer->_scenesApex.at(index); _selectedPos->_apex = apex; _selectedPos->_hasApex = true; } colorizeScenes(); redrawOverlayAnd3D(); } void ONF_ActionSelectSceneForEachPosition::redrawOverlay() { document()->redrawGraphics(); } void ONF_ActionSelectSceneForEachPosition::redrawOverlayAnd3D() { setDrawing3DChanged(); document()->redrawGraphics(); } void ONF_ActionSelectSceneForEachPosition::updateColorization() { colorizeScenes(); redrawOverlayAnd3D(); } bool ONF_ActionSelectSceneForEachPosition::mousePressEvent(QMouseEvent *e) { if(_segmentMode) { return _selectTool->mousePressEvent(e); } else { _lastPos = e->pos(); _buttonsPressed = e->buttons(); } return false; } bool ONF_ActionSelectSceneForEachPosition::mouseMoveEvent(QMouseEvent *e) { if(_segmentMode) { return _selectTool->mouseMoveEvent(e); } return false; } bool ONF_ActionSelectSceneForEachPosition::mouseReleaseEvent(QMouseEvent *e) { if(_segmentMode) { return _selectTool->mouseReleaseEvent(e); } else { GraphicsViewInterface *view = graphicsView(); QPoint dir = e->pos() - _lastPos; if (dir.manhattanLength() < 3) { if (_buttonsPressed == Qt::RightButton) { Eigen::Vector3d origin, direction; view->convertClickToLine(e->pos(), origin, direction); _selectedPos = getPositionFromDirection(origin, direction); colorizeScenes(); redrawOverlayAnd3D(); } else if (_buttonsPressed == Qt::LeftButton) { #ifdef COMPUTREE_V5 QRect r(0, 0, 3, 3); r.moveCenter(e->pos()); view->select(r); #else view->setSelectRegionWidth(3); view->setSelectRegionHeight(3); view->select(e->pos()); #endif redrawOverlayAnd3D(); return false; } } } return false; } bool ONF_ActionSelectSceneForEachPosition::wheelEvent(QWheelEvent *e) { if(_segmentMode) { return _selectTool->wheelEvent(e); } return false; } bool ONF_ActionSelectSceneForEachPosition::keyPressEvent(QKeyEvent *e) { if(_segmentMode) { return _selectTool->keyPressEvent(e); } else { if((e->key() == Qt::Key_A) && !e->isAutoRepeat()) { addCluster(); } if((e->key() == Qt::Key_Z) && !e->isAutoRepeat()) { removeCluster(); } if((e->key() == Qt::Key_E) && !e->isAutoRepeat()) { switchCluster(); } } return false; } bool ONF_ActionSelectSceneForEachPosition::keyReleaseEvent(QKeyEvent *e) { if(_segmentMode) { return _selectTool->keyReleaseEvent(e); } return false; } void ONF_ActionSelectSceneForEachPosition::draw(GraphicsViewInterface &view, PainterInterface &painter) { if (!_segmentMode) { for (int i = 0 ; i < _dataContainer->_positions.size() ; i++) { ONF_ActionSelectSceneForEachPosition_treePosition* treePos = _dataContainer->_positions.at(i); drawCylinder(view, painter, treePos); } } } void ONF_ActionSelectSceneForEachPosition::drawOverlay(GraphicsViewInterface &view, QPainter &painter) { if(_segmentMode) { return _selectTool->drawOverlay(view, painter); } else { painter.save(); int add = painter.fontMetrics().height()+2; int y = add; QString txt; bool showLog = _previousSelectedPos != _selectedPos; _previousSelectedPos = _selectedPos; QString logMessage = ""; if (showLog && _selectedPos == NULL) { logMessage.append("-------------------------------------
"); logMessage.append(tr("No selected Tree
")); PS_LOG->addMessage(LogInterface::info, LogInterface::action, logMessage); } if (_selectedPos != NULL) { if (showLog) { logMessage.append("-------------------------------------
"); logMessage.append("Selected Tree informations:
"); } painter.setPen(QColor(255,255,255)); txt = QString("Plot: %1 ; Tree: %2").arg(_selectedPos->_idPlot).arg(_selectedPos->_idTree); painter.drawText(2, y, txt); y += add; if (showLog) {logMessage.append(QString("%1
").arg(txt));} txt = QString("DBH: %1 cm").arg(_selectedPos->_dbh); painter.drawText(2, y, txt); y += add; if (showLog) {logMessage.append(QString("%1
").arg(txt));} txt = QString("H: %1 m").arg(_selectedPos->_height); painter.drawText(2, y, txt); y += add; if (showLog) {logMessage.append(QString("%1
").arg(txt));} txt = QString("Species: %1").arg(_selectedPos->_species); painter.drawText(2, y, txt); y += add; if (showLog) {logMessage.append(QString("%1
").arg(txt));} double dist = -1; if (_selectedPos->_hasApex) { dist = sqrt(pow(_selectedPos->_apex(0) - _selectedPos->_base(0), 2) + pow(_selectedPos->_apex(1) - _selectedPos->_base(1), 2)); dist = std::round(dist * 100.0) / 100.0; } txt = QString("XY Distance: %1 m").arg(dist); painter.drawText(2, y, txt); y += add; if (showLog) {logMessage.append(QString("%1
").arg(txt));} if (showLog) { PS_LOG->addMessage(LogInterface::info, LogInterface::action, logMessage); } } painter.restore(); } } CT_AbstractAction* ONF_ActionSelectSceneForEachPosition:: copy() const { return new ONF_ActionSelectSceneForEachPosition(_dataContainer); } ONF_ActionSelectSceneForEachPosition_treePosition* ONF_ActionSelectSceneForEachPosition::getPositionFromDirection(Eigen::Vector3d &origin, Eigen::Vector3d &direction) { ONF_ActionSelectSceneForEachPositionOptions *option = (ONF_ActionSelectSceneForEachPositionOptions*)optionAt(0); double minDist = std::numeric_limits::max(); ONF_ActionSelectSceneForEachPosition_treePosition* pos = NULL; for (int i = 0 ; i < _dataContainer->_positions.size() ; i++) { ONF_ActionSelectSceneForEachPosition_treePosition* treePos = _dataContainer->_positions.at(i); Eigen::Vector3d treeDirection = treePos->_apex - treePos->_base; double apexLength = treeDirection.norm(); treeDirection.normalize(); double treeHeight = treePos->_height; if (treePos->_height == -1) {treeHeight = option->defaultHeight();} double treeLength = treeHeight; if (treePos->_hasApex && treePos->_apex(2) != treePos->_base(2)) { treeLength = apexLength * (treeHeight / (treePos->_apex(2) - treePos->_base(2))); } else { apexLength = treeHeight; treeDirection = Eigen::Vector3d(0,0,1); } treeLength = std::max(apexLength, treeLength); for (double l = 0 ; l < treeLength ; l += 0.1) { Eigen::Vector3d point = treePos->_base + treeDirection*l; double distance = CT_MathPoint::distancePointLine(point, direction, origin); if (distance < minDist) { minDist = distance; pos = treePos; } } } if (minDist > 5.0) {return NULL;} return pos; } bool ONF_ActionSelectSceneForEachPosition::getCoordsForMousePosition(QPoint p, double &x, double &y) { Eigen::Vector3d origin, direction; GraphicsViewInterface *view = graphicsView(); view->convertClickToLine(p, origin, direction); if (direction.z() == 0) {return false;} double coef = (0.0 - origin.z())/direction.z(); x = origin.x() + coef*direction.x(); y = origin.y() + coef*direction.y(); return true; } void ONF_ActionSelectSceneForEachPosition::drawCylinder(GraphicsViewInterface &view, PainterInterface &painter, ONF_ActionSelectSceneForEachPosition_treePosition* treePos) const { Q_UNUSED(view); ONF_ActionSelectSceneForEachPositionOptions *option = (ONF_ActionSelectSceneForEachPositionOptions*)optionAt(0); if (_selectedPos != NULL) { double dist = sqrt(pow(treePos->_base(0) - _selectedPos->_base(0), 2) + pow(treePos->_base(1) - _selectedPos->_base(1), 2)); if (dist > option->visibleDist()) { return; } } bool isHighlighted = false; for (int i = 0 ; i < option->highlightedNumberOfTrees() ; i++) { if (_dataContainer->_positions.at(i) == treePos) { isHighlighted = true; } } Eigen::Vector3d direction = treePos->_apex - treePos->_base; double apexLength = direction.norm(); direction.normalize(); double treeHeight = treePos->_height; if (treePos->_height == -1) {treeHeight = option->defaultHeight();} double treeLength = treeHeight; if (treePos->_hasApex && treePos->_apex(2) != treePos->_base(2)) { treeLength = apexLength * (treeHeight / (treePos->_apex(2) - treePos->_base(2))); } else { apexLength = treeHeight; direction = Eigen::Vector3d(0,0,1); } double radius = treePos->_dbh / 200.0; if (!option->diameters()) {radius = 0.05;} QColor color = painter.getColor(); QColor color1 = _cylinderColor1; QColor color2 = _cylinderColor2; if (treePos == _selectedPos) { color1 = _selectedCylinderColor1; color2 = _selectedCylinderColor2; } else if (isHighlighted) { color1 = _highlightedCylindersColor1; color2 = _highlightedCylindersColor2; } if (treeLength == apexLength) { painter.setColor(color1); if(option->circles()) { for (double l = 0 ; l < apexLength ; l += 0.50) { Eigen::Vector3d circleCenter = treePos->_base + direction * l; painter.drawCircle3D(circleCenter, direction, radius); } } else { Eigen::Vector3d center = treePos->_base + direction*apexLength/2.0; painter.drawCylinder3D(center, direction, radius, apexLength); } } else if (treeLength < apexLength) { painter.setColor(color1); if(option->circles()) { for (double l = 0 ; l < treeLength ; l += 0.50) { Eigen::Vector3d circleCenter = treePos->_base + direction * l; painter.drawCircle3D(circleCenter, direction, radius); } } else { Eigen::Vector3d center = treePos->_base + direction*treeLength/2.0; painter.drawCylinder3D(center, direction, radius, treeLength); } painter.setColor(color2); Eigen::Vector3d newBase = treePos->_base + direction * treeLength; double deltaL = apexLength - treeLength; if(option->circles()) { for (double l = 0 ; l < deltaL ; l += 0.50) { Eigen::Vector3d circleCenter = newBase + direction * l; painter.drawCircle3D(circleCenter, direction, radius); } } else { Eigen::Vector3d center = newBase + direction*deltaL/2.0; painter.drawCylinder3D(center, direction, radius, deltaL); } } else { painter.setColor(color1); if(option->circles()) { for (double l = 0 ; l < apexLength ; l += 0.50) { Eigen::Vector3d circleCenter = treePos->_base + direction * l; painter.drawCircle3D(circleCenter, direction, radius); } } else { Eigen::Vector3d center = treePos->_base + direction*apexLength/2.0; painter.drawCylinder3D(center, direction, radius, apexLength); } painter.setColor(color2); Eigen::Vector3d newBase = treePos->_base + direction * apexLength; double deltaL = treeLength - apexLength; if(option->circles()) { for (double l = 0 ; l < deltaL ; l += 0.50) { Eigen::Vector3d circleCenter = newBase + direction * l; painter.drawCircle3D(circleCenter, direction, radius); } } else { Eigen::Vector3d center = newBase + direction*deltaL/2.0; painter.drawCylinder3D(center, direction, radius, deltaL); } } painter.setColor(color); }