diff options
| author | Mikko Syrjä <mikko@3d-system.fi> | 2019-02-26 21:30:44 +0200 |
|---|---|---|
| committer | Mikko Syrjä <mikko@3d-system.fi> | 2019-02-26 21:30:44 +0200 |
| commit | de0acfd2b1e83c58659f9293e1b23f196a14ef9e (patch) | |
| tree | 43dc3cac8a130ef8a890724ad44a623c91783fb5 | |
| parent | 498b1b9a56b399225d3a70742fdcb01245aa91c4 (diff) | |
| download | symedit-de0acfd2b1e83c58659f9293e1b23f196a14ef9e.tar.gz symedit-de0acfd2b1e83c58659f9293e1b23f196a14ef9e.zip | |
Implement nearest item selection.
| -rw-r--r-- | Editor.qml | 37 | ||||
| -rw-r--r-- | symbol.cpp | 72 | ||||
| -rw-r--r-- | symbol.h | 2 | ||||
| -rw-r--r-- | symedit.cpp | 85 | ||||
| -rw-r--r-- | symedit.h | 2 |
5 files changed, 141 insertions, 57 deletions
@@ -47,20 +47,27 @@ Rectangle onPositionChanged: { - mousex = Math.round((mouse.x - canvas.x) / scalexy / snapgrid) * snapgrid - max - offset - mousey = max - Math.round((mouse.y - canvas.y) / scalexy / snapgrid) * snapgrid + offset - - if ( mousex < -max) - mousex = -max - else if ( mousex > max ) - mousex = max - if ( mousey < -max ) - mousey = -max - else if ( mousey > max ) - mousey = max - - if ( down ) - canvas.requestPaint() + if ( tool === Editor.Tool.Select ) + { + mousex = Math.round((mouse.x - canvas.x) / scalexy) - max - offset + mousey = max - Math.round((mouse.y - canvas.y) / scalexy) + offset + } + else // snap and clip + { + mousex = Math.round((mouse.x - canvas.x) / scalexy / snapgrid) * snapgrid - max - offset + mousey = max - Math.round((mouse.y - canvas.y) / scalexy / snapgrid) * snapgrid + offset + if ( mousex < -max) + mousex = -max + else if ( mousex > max ) + mousex = max + if ( mousey < -max ) + mousey = -max + else if ( mousey > max ) + mousey = max + + if ( down ) + canvas.requestPaint() + } } onPressed: @@ -82,7 +89,7 @@ Rectangle { endx = mousex endy = mousey - if ( startx != endx && starty != endy ) + if ( startx != endx || starty != endy ) { if ( tool === Editor.Tool.Line ) { @@ -99,7 +99,7 @@ QString& SymEditSymbol::Save(QString& buffer) const position = item.Value; break; } - case 'R': + case 'R': // circle { if ( item.Point != position ) appendvalue(buffer.append('U'), item.Point, 2); @@ -155,63 +155,99 @@ SymEditSymbol::Item& SymEditSymbol::AddItem(int operation, QPoint point, QString //! Remove item. /*! \param index Item index. + \return True for success. */ -void SymEditSymbol::RemoveItem(int index) +bool SymEditSymbol::RemoveItem(int index) { if ( static_cast<size_t>(index) < Items.size() ) { Items.erase(Items.begin() + index); ActiveIndex = index - 1; + return true; } + return false; } -// +//! Select item nearest to point. +/*! + \param point Point coordinates. + \return Nearest item index. +*/ int SymEditSymbol::SelectItem(QPoint point) const { ActiveIndex = -1; int index = 0; - QPoint previous(0, 0); double minimum = 100.0; + + auto difference = [](const QPoint& start, const QPoint& end) { return QPoint(end.x() - start.x(), end.y() - start.y()); }; + auto length = [](const QPoint& point) { return sqrt(point.x() * point.x() + point.y() * point.y()); }; + auto scalar = [](const QPoint& start, const QPoint& end) { return static_cast<double>(start.x() * end.x() + start.y() * end.y()); }; + auto cross = [](const QPoint& start, const QPoint& end) { return static_cast<double>(start.x() * end.y() - start.y() * end.x()); }; + auto projection = [&](const QPoint& point, const QPoint& start, const QPoint& end) + { + QPoint line = difference(start, end); + return scalar(difference(start, point), line) / length(line); + }; + auto check = [&](double distance) + { + if ( ActiveIndex < 0 || distance < minimum ) + { + ActiveIndex = index; + minimum = distance; + } + }; + + auto distance = [&](const QPoint& point, const QPoint& start, const QPoint& end) + { + QPoint line = difference(start, end); + double len = length(line), a = projection(point, start, end); + if ( a > 0.0 && a < len ) + check(fabs(cross(difference(start, point), line) / len)); + check(length(difference(point, start))); + check(length(difference(point, end))); + }; + for ( const auto& item : Items ) { switch ( item.Operation ) { case 'D': // line { - //## + distance(point, item.Point, item.Value); break; } case 'B': // rectangle { - //## + distance(point, item.Point, QPoint(item.Point.x(), item.Value.y())); + distance(point, QPoint(item.Point.x(), item.Value.y()), item.Value); + distance(point, item.Value, QPoint(item.Value.x(), item.Point.y())); + distance(point, QPoint(item.Value.x(), item.Point.y()), item.Point); break; } case 'R': // circle { - double dx = point.x() - previous.x(); - double dy = point.y() - previous.y(); - double distance = sqrt(dx * dx + dy * dy); - distance = abs(distance - item.Point.x()); - if ( ActiveIndex < 0 || distance < minimum ) - { - ActiveIndex = index; - minimum = distance; - } + check(fabs(length(difference(point, item.Point)) - item.Value.x())); break; } } ++index; } - return static_cast<int>(ActiveIndex); + return ActiveIndex; } -// +//! Set active item index. +/*! + \param index Active item index. +*/ void SymEditSymbol::SetActiveIndex(int index) { ActiveIndex = index; } -// +//! Get active item index. +/*! + \return Active item index. +*/ int SymEditSymbol::GetActiveIndex() const { return static_cast<int>(ActiveIndex); @@ -34,7 +34,7 @@ public: Item& AddItem(int operation, QPoint point, int value, int fill); Item& AddItem(int operation, QPoint point, QPoint end, int fill); Item& AddItem(int operation, QPoint point, QString text, int align); - void RemoveItem(int index); + bool RemoveItem(int index); int SelectItem(QPoint point) const; void SetActiveIndex(int index); diff --git a/symedit.cpp b/symedit.cpp index 1138d66..0c9d831 100644 --- a/symedit.cpp +++ b/symedit.cpp @@ -180,10 +180,17 @@ void SymEditManager::addTextItem(int operation, QPoint point, QString value, int } //! Remove active item. -void SymEditManager::removeItem() +/*! + \return True for success. +*/ +bool SymEditManager::removeItem() { - undosave(); - Symbol.RemoveItem(Symbol.GetActiveIndex()); + if ( Symbol.GetItemCount() ) + { + undosave(); + return Symbol.RemoveItem(Symbol.GetActiveIndex()); + } + return false; } //! Get item count. @@ -202,8 +209,12 @@ int SymEditManager::getItemCount() const */ int SymEditManager::getItemOperation(int index) const { - const auto& item = Symbol.GetItem(index); - return item.Operation; + if ( Symbol.GetItemCount() ) + { + const auto& item = Symbol.GetItem(index); + return item.Operation; + } + return 0; } //! Get item position. @@ -213,10 +224,14 @@ int SymEditManager::getItemOperation(int index) const */ QPoint SymEditManager::getItemPosition(int index) const { - const auto& item = Symbol.GetItem(index); - if ( item.Operation == 'B' ) // normalize to upper left - return QPoint(std::min(item.Value.x(), item.Point.x()), std::max(item.Value.y(), item.Point.y())); - return item.Point; + if ( Symbol.GetItemCount() ) + { + const auto& item = Symbol.GetItem(index); + if ( item.Operation == 'B' ) // normalize to upper left + return QPoint(std::min(item.Value.x(), item.Point.x()), std::max(item.Value.y(), item.Point.y())); + return item.Point; + } + return QPoint(0, 0); } //! Get item int value. @@ -226,8 +241,12 @@ QPoint SymEditManager::getItemPosition(int index) const */ int SymEditManager::getItemValue(int index) const { - const auto& item = Symbol.GetItem(index); - return item.Value.x(); + if ( Symbol.GetItemCount() ) + { + const auto& item = Symbol.GetItem(index); + return item.Value.x(); + } + return 0; } //! Get item point value. @@ -237,10 +256,14 @@ int SymEditManager::getItemValue(int index) const */ QPoint SymEditManager::getItemPoint(int index) const { - const auto& item = Symbol.GetItem(index); - if ( item.Operation == 'B' ) // normalize to lower right - return QPoint(std::max(item.Value.x(), item.Point.x()), std::min(item.Value.y(), item.Point.y())); - return item.Value; + if ( Symbol.GetItemCount() ) + { + const auto& item = Symbol.GetItem(index); + if ( item.Operation == 'B' ) // normalize to lower right + return QPoint(std::max(item.Value.x(), item.Point.x()), std::min(item.Value.y(), item.Point.y())); + return item.Value; + } + return QPoint(0, 0); } //! Get item text value. @@ -250,30 +273,48 @@ QPoint SymEditManager::getItemPoint(int index) const */ QString SymEditManager::getItemText(int index) const { - const auto& item = Symbol.GetItem(index); - return item.Text; + if ( Symbol.GetItemCount() ) + { + const auto& item = Symbol.GetItem(index); + return item.Text; + } + return ""; } // int SymEditManager::getItemFill(int index) const { - const auto& item = Symbol.GetItem(index); - return item.Fill; + if ( Symbol.GetItemCount() ) + { + const auto& item = Symbol.GetItem(index); + return item.Fill; + } + return 0; } -// +//! Select item nearest to point. +/*! + \param point Point coordinates. + \return Nearest item index. +*/ int SymEditManager::selectItem(QPoint point) const { return Symbol.SelectItem(point); } -// +//! Set active item index. +/*! + \param index Active item index. +*/ void SymEditManager::setActiveIndex(int index) { Symbol.SetActiveIndex(index); } -// +//! Get active item index. +/*! + \return Active item index. +*/ int SymEditManager::getActiveIndex() const { return Symbol.GetActiveIndex(); @@ -69,7 +69,7 @@ public: Q_INVOKABLE void addValueItem(int operation, QPoint point, int value, int fill); Q_INVOKABLE void addPointItem(int operation, QPoint point, QPoint value, int fill); Q_INVOKABLE void addTextItem(int operation, QPoint point, QString value, int align); - Q_INVOKABLE void removeItem(); + Q_INVOKABLE bool removeItem(); Q_INVOKABLE int getItemCount() const; Q_INVOKABLE int getItemOperation(int index) const; |
