aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikko Syrjä <mikko@3d-system.fi>2019-02-26 21:30:44 +0200
committerMikko Syrjä <mikko@3d-system.fi>2019-02-26 21:30:44 +0200
commitde0acfd2b1e83c58659f9293e1b23f196a14ef9e (patch)
tree43dc3cac8a130ef8a890724ad44a623c91783fb5
parent498b1b9a56b399225d3a70742fdcb01245aa91c4 (diff)
downloadsymedit-de0acfd2b1e83c58659f9293e1b23f196a14ef9e.tar.gz
symedit-de0acfd2b1e83c58659f9293e1b23f196a14ef9e.zip
Implement nearest item selection.
-rw-r--r--Editor.qml37
-rw-r--r--symbol.cpp72
-rw-r--r--symbol.h2
-rw-r--r--symedit.cpp85
-rw-r--r--symedit.h2
5 files changed, 141 insertions, 57 deletions
diff --git a/Editor.qml b/Editor.qml
index b05c3d9..b7aef56 100644
--- a/Editor.qml
+++ b/Editor.qml
@@ -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 )
{
diff --git a/symbol.cpp b/symbol.cpp
index f95ba71..ea24933 100644
--- a/symbol.cpp
+++ b/symbol.cpp
@@ -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);
diff --git a/symbol.h b/symbol.h
index 2ee996c..7bd0237 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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();
diff --git a/symedit.h b/symedit.h
index f10a07a..ba6e822 100644
--- a/symedit.h
+++ b/symedit.h
@@ -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;